Есть задача:
Запросить путь на папку с консоли, получить список всех папок заданной папки с учетом иерархии.
Например, поиск в папке "book" даст 5 элементов:
-book
--directory1
---file1
---file2
--directory2
---directory3
----directory4
-----directory5
------file3
Частичная реализация выглядит так:
public static void main(String[] args) {
String scan = new Scanner(System.in).nextLine();
System.out.println(scan);
File dir = new File(String.valueOf(scan));
if ( dir.isDirectory() ) {
File[] files = dir.listFiles();
for ( File tmpFile : files ) {
System.out.println("-" + tmpFile.getName());
if ( tmpFile.isDirectory() ) {
File[] tmpFile1 = tmpFile.listFiles();
for ( File file3 : tmpFile1 ) {
System.out.println("--" + file3.getName());
}
}
}
}
}
Результат:
d://book
-directory1
--file1.txt
--file2.txt
-directory2
--directory3
Результат выдает данные только до третьей директории, и ума не приложу как исправить код и довести задачу до конца.
Не поверите, полчаса голову ломал, так и не смог придумать решение без рекурсии. Вот код, который у меня получился
public class Main
{
static String counter = "-";
public static void main(String[] args)
{
System.out.println("Путь к папке");
Scanner s = new Scanner(System.in);
String path = s.nextLine();
File dir = new File(path);
if(!dir.exists()){
System.out.println("Папки с введеным именем не существует");
}
else if(!dir.isDirectory()){
System.out.println("Не является папкой");
}
else {
printAllFilesFromDirectory(dir);
}
}
static void printAllFilesFromDirectory(File dir){
for(File file : dir.listFiles()) {
print(file);
if(file.isDirectory()) {
counter += "-";
printAllFilesFromDirectory(file);
}
}
counter -= "-";
}
static void print(File file){
System.out.println(counter + " " + file.getName());
}
}
После проверок "на дурака" введеный путь передается в метод printAllFilesFromDirectory
. В нем каждый файл передается методу print()
, в котором выводятся тире и его имя. Количество тире опрелеляется счетчиком counter
(его значение по умолчанию равно единице). После метода print
если файл является директорией мы инкрементируем счетчик, так как уровень иерархии увеличился. После этого мы выполняем метод с помощью рекурсии и передаем ему директорию.
В итоге этот метод будет выводить все файлы и директории с учетом иерархии. Обратите внимание на декремент counter
. Он происходит когда все файлы будут выведены! (Директории - нет, в этом случае происходит рекурсия)
Да, знаю, если путь будет слишком большой, то рекурсия станет причиной переполнения стека. Повторюсь: я не смог придумать другое решение :)
UPDATE
Теперь counter
это строка (метод print
выглядел по-уродски.
В стандартной библиотеке есть замечательный класс Files
, в нем есть статический метод walkFileTree
. Он нужен именно для того, что вы хотите. Т.е. для обхода дерева каталогов.
Код будет следующий:
Path parent = Paths.get("<корневая директория>");
Files.walkFileTree(parent, new SimpleFileVisitor<Path>() {
@Override
public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException {
int count = dir.getNameCount() - parent.getNameCount() + 1;
count += dir.getFileName().toString().length();
//выравнивание по правому краю
String text = String.format("%" + count + "s", dir.getFileName());
text = text.replaceAll("[\\s]", "-");
System.out.println(text);
return FileVisitResult.CONTINUE;
}
});
Вместо рекурсии можно использовать стек:
private static class Element
{
public final String indent;
public final File file;
public Element(String indent, File file)
{
this.indent = indent;
this.file = file;
}
public String toString()
{
return indent + file.getName();
}
}
public static void main(String[] args)
{
Scanner scanner = new Scanner(System.in);
String path = scanner.nextLine();
File dir = new File(path);
if (!dir.exists() || !dir.isDirectory())
{
System.out.println("Incorrect directory name");
}
Deque<Element> stack = new ArrayDeque<>();
stack.add(new Element("-", dir));
while (!stack.isEmpty())
{
Element element = stack.pollLast();
System.out.println(element);
if (element.file.isDirectory())
{
File[] files = element.file.listFiles();
for (int i = files.length - 1; i >=0; i--)
{
stack.add(new Element(element.indent + "-", files[i]));
}
}
}
}
Идея остаётся та же: берём очередной файл/директорию, выводим на экран, после чего, если это директория, добавляем в обработку содержимое этой папки. И так до тех пор, пока есть что обрабатывать.
Оборудование для ресторана: новинки профессиональной кухонной техники
Частный дом престарелых в Киеве: комфорт, забота и профессиональный уход
Закончил изучать swing и решил попробовать javaFx, буквально с самого начала у меня появилась проблемаКак можно установить layout в JavaFX? (на данный...
Есть сервер на джаве, пишу к нему сайтПри отправке запроса POST выдает
У меня есть сервис который с определенным интервалом подключается к серверу и сверяет последний id в БДЕсли на сервере id больше, чем у меня...