Недавно возникла потребность написать небольшой код, который будет содержать рекурсию. Задача была довольно таки простой: вывести содержимое папки до самого последнего уровня вложенности. Важное требование - древовидная форма вывода. Дня 3 ходил и прикидывал в голове, какой будет метод для рекурсивной функции... В голове сформировалось даже несколько подходов и каждый из них был более чем рабочим.
Само-собой пришло время сесть и написать хотя бы одну реализацию. Сел, раскрыл Java API для работы с File'ами. Набросал несколько небольших семплов и решил, что этого уже достаточно для решения задачи... Чего я только не написал за тот вечер, было все, что угодно, только не решение. До бешенства доводили бесконечные циклы и ничего с этим поделать нельзя было.
Решил оставить написание кода на утро.
Создал два класса:
import java.io.File;
public class Recurse {
int level = 0;
String spaces = "";
public void starter(String path) {
File rootDir = new File(path);
if (rootDir.isFile())
System.out.println(spaces+"[F] "+rootDir.getName());
if (rootDir.isDirectory()) {
System.out.println(spaces+"[D] "+rootDir.getName());
File[] innerList = rootDir.listFiles();
if (innerList.length > 0) {
level++;
spaces += " ";
for (File f : innerList) {
starter(f.getPath());
}
}
level--;
spaces = spaces.substring(0, spaces.length()-1);
}
}
}
public class FilePolygon {
public static void main(String[] args) {
Recurse r = new Recurse();
do {
r.starter("E:\\RootDir");
} while (r.level > 0);
}
}
К моему большому удивлению, все получилось с первого раза. Поэтому я рассчитываю, что этот код может содержать ошибки. Тестил свою рекурсию на этой папке. Можете ее выкачать и попробовать провести свои испытания. Буду рад прочитать отзывы.
UPDATE:
Огромное спасибо Андрею Нестеренко за оперативный отзыв и внесение замечаний по работе метода. После ряда правок, получаем новый вариант кода, который более лаконичен и не выдает ошибок при некоторых структурах директорий и файлов в них.import java.io.File;
public class Recurse {
String spaces = "";
public void starter(String path) {
File rootDir = new File(path);
if (rootDir.isFile())
System.out.println(spaces+"[F] "+rootDir.getName());
if (rootDir.isDirectory()) {
System.out.println(spaces+"[D] "+rootDir.getName());
File[] innerList = rootDir.listFiles();
if (innerList.length == 0)
return;
spaces += " ";
for (File f : innerList) {
starter(f.getPath());
}
spaces = spaces.substring(0, spaces.length()-2);
}
}
}
public class FilePolygon {
public static void main(String[] args) {
Recurse r = new Recurse();
r.starter("E:\\RootDir");
}
}
Результат улучшился налицо! Ушла такая переменная, как int level. Появился оператор return, который в случае нулевой длины innerList, передаст управление вызывающему его объекту.
Если ваша программа заработала с первого раза, то без сомнений сообщите создателям компилятора, что у них продукт с дефектом ©

С виду все правильно кроме одного. К spaces добавляется 2 пробела, а удаляется только один.
ОтветитьУдалитьОказывается только с виду все было правильно =)
УдалитьА команда "ls -R" вижу вам чужда?
ОтветитьУдалитьЛеша, довольно-таки интересную тему затронул :)
ОтветитьУдалитьНе дал покоя мне твой код и на досуге решил покопаться в нем. Вылетает эксепшн при такой структуре каталога:
RootDir
Dir1
Dir2
Dir21
file.txt
Dir3
Плюс к этому, если директория не содержала бы вообще каталогов, то программа вылетала также.
Мне было интересно, как можно изменить твой код (улучшить, укоротить, убрать эксепшены) и в итоге, я немного подкорректировал код класса Recurse и получил следующую версию:
import java.io.File;
public class Recurse {
public void starter(String path) {
String spaces = "";
File rootDir = new File(path);
if (rootDir.isFile())
{
System.out.println(spaces+"[F] "+rootDir.getName());
}
else
{
System.out.println(spaces+"[D] "+rootDir.getName());
File[] innerList = rootDir.listFiles();
if (innerList.length == 0)
{
return;
}
spaces += " ";
for (File f : innerList)
{
starter(f.getPath());
}
spaces = spaces.substring(0, spaces.length() - 2);
}
}
}
к сожалению blogspot не позволяет редактировать собственные комментарии( я чуть ошибся, скопировав не то. Вот эта версия правильная:
ОтветитьУдалитькласс Recurse:
import java.io.File;
public class Recurse {
String spaces = "";
public void starter(String path) {
File rootDir = new File(path);
if (rootDir.isFile())
{
System.out.println(spaces+"[F] "+rootDir.getName());
}
else
{
System.out.println(spaces+"[D] "+rootDir.getName());
File[] innerList = rootDir.listFiles();
if (innerList.length == 0)
return;
spaces += " ";
for (File f : innerList)
{
starter(f.getPath());
}
spaces = spaces.substring(0, spaces.length() - 2);
}
}
}
Класс FilePolygon:
public class FilePolygon {
public static void main(String[] args) {
Recurse r = new Recurse();
r.starter("D:\\RootDir"); }
}
Спасибо за обширный коммент =)
УдалитьСтавлю себе TODO пункт на обновление своего поста, согласно твоим замечаниям =)
В ближайшие дни будет апдейт =)