Рекурсивный метод, возвращающий пустое значение - PullRequest
3 голосов
/ 20 января 2020

Описание

Моя цель - сохранить все пути к файлам в файле. Для этого я создал рекурсивный метод, который просматривает указанную папку c. Тем не менее, результат все еще пуст ...

Код

public void main(String[] args) {
    String files = browseFolder("", new File("blablalbla/.../toto"));

    FileWriter writer = new FileWriter(new File("result/"));
    writer.write(files);
    writer.close();
}

private static String browseFolder(String result, File folder) {
    for (final File fileEntry : folder.listFiles()) {
        if (fileEntry.isDirectory()) {
            browseFolder(result, fileEntry);
        }
        else {
            System.out.println(fileEntry.getPath());
            result += fileEntry.getPath() + "\n";
        }
    }
    return result;
}

Все файлы отображаются в консоли благодаря sysout. Тем не менее, мой файл результатов пуст.

Есть идеи? Спасибо.

Ответы [ 3 ]

3 голосов
/ 20 января 2020

Из-за неизменности String (переменная result всегда ссылается на одно и то же строковое значение в памяти), вы должны использовать concat для сохранения результата, поскольку он фактически создает новую ссылку на новое строковое значение.

if (fileEntry.isDirectory()) {
    result += browseFolder(result, fileEntry);
}
2 голосов
/ 20 января 2020

Обратите внимание, что рекурсивный вызов browseFolder не изменит свой параметр, поскольку String является неизменным. Строковая переменная, которая передается методу, всегда остается неизменной после возврата этого метода. Это означает, что пока каталог blablalbla/.../toto заполнен подкаталогами, ваш основной вызов browseFolder будет возвращать пустую строку, потому что вы ничего не делаете для result.

You может добавить возвращаемое значение рекурсивных browseFolder вызовов к result, например:

private static String browseFolder(String result, File folder) {
    for (final File fileEntry : folder.listFiles()) {
        if (fileEntry.isDirectory()) {
            // here:
            result += browseFolder(result, fileEntry);
        }
        else {
            System.out.println(fileEntry.getPath());
            result += fileEntry.getPath() + "\n";
        }
    }
    return result;
}

Однако, это создает новую строку каждый раз, когда вы делаете это, так что это довольно расточительно. Вместо этого вы можете использовать StringBuilder (который может изменяться!).

private static StringBuilder browseFolder(StringBuilder result, File folder) {
    for (final File fileEntry : folder.listFiles()) {
        if (fileEntry.isDirectory()) {
            browseFolder(result, fileEntry);
        }
        else {
            System.out.println(fileEntry.getPath());
            result.append(fileEntry.getPath()).append("\n");
        }
    }
    return result;
}

Вызывающий абонент также должен будет измениться. Вы можете сделать .toString на StringBuilder, чтобы преобразовать его в String.

String files = browseFolder(new StringBuilder(), new File("blablalbla/.../toto")).toString();
2 голосов
/ 20 января 2020

В

browseFolder(result, fileEntry);

вы игнорируете String, возвращаемый рекурсивным методом, поэтому в конце вы получаете пустое String.

Вместо конкатенации String s, что приводит к созданию многих String экземпляров, я предлагаю вам передать StringBuilder вашему рекурсивному методу.

Таким образом, ваш метод может изменить StringBuilder и не имеет вернуть значение.

public void main(String[] args) {
    StringBuilder files = new StringBuilder();
    browseFolder(files, new File("blablalbla/.../toto"));

    FileWriter writer = new FileWriter(new File("result/"));
    writer.write(files.toString());
    writer.close();
}

private static void browseFolder(StringBuilder result, File folder) {
    for (final File fileEntry : folder.listFiles()) {
        if (fileEntry.isDirectory()) {
            browseFolder(result, fileEntry);
        } else {
            System.out.println(fileEntry.getPath());
            result.append(fileEntry.getPath()).append("\n");
        }
    }
}
...