logo

Обход файлов и подпапок в Java: итерация и обработка файлов

Быстрый ответ

Для рекурсивного обхода директорий в Java необходимо воспользоваться методом Files.walk. Вот пример его применения:

Java
Скопировать код
try (Stream<Path> files = Files.walk(Path.of("dir"))) {
    files.forEach(System.out::println);
}

Этот код создаёт поток путей, выводя информацию об каждом файле и директории, начиная с "dir".

Обход символических ссылок с Files.walk

Применяя Files.walk, следует учесть циклические символические ссылки, способные вызвать бесконечную рекурсию. Для предотвращения этой проблемы можно использовать опцию FileVisitOption.FOLLOW_LINKS и установить параметр maxDepth:

Java
Скопировать код
Files.walk(Path.of("dir"), maxDepth, FileVisitOption.FOLLOW_LINKS);

Пользовательский обход директорий с Files.walkFileTree

Если требуется большая гибкость и контроль над процессом, стоит использовать Files.walkFileTree с расширением FileVisitor:

Java
Скопировать код
Files.walkFileTree(Path.of("dir"), new SimpleFileVisitor<Path>() {
    @Override
    public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) {
        System.out.println(file); // Привет, файл!
        return FileVisitResult.CONTINUE;
    }
    // Переопределите другие методы для расширения возможностей
});

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

Использование Apache Commons IO

Если хочется абстрагироваться от низкоуровневых операций, применение Apache Commons IO и функции FileUtils.listFiles может быть оптимальной стратегией:

Java
Скопировать код
Collection<File> files = FileUtils.listFiles(
  new File("dir"), 
  TrueFileFilter.INSTANCE, 
  DirectoryFileFilter.DIRECTORY
);

files.forEach(System.out::println); // Вот это печать!

Библиотека Apache Commons IO предлагает простой и надежный способ для обхода, избавляя от рутины написания кода.

Фильтрация файлов с Files.newDirectoryStream

С Java 7 и посредством Files.newDirectoryStream есть возможность одновременно обходить директории и фильтровать файлы:

Java
Скопировать код
try (DirectoryStream<Path> stream = Files.newDirectoryStream(dir, "*.java")) {
    for (Path entry : stream) {
        System.out.println(entry); // Разыскивается файл!
    }
} catch (IOException | DirectoryIteratorException ex) {
    // Обработка исключения
}

Этот метод органично сочетает использование DirectoryStream с фильтрацией файлов по их расширению.

Обработка исключений в DirectoryStream

Неожиданные DirectoryIteratorExceptions могут возникнуть во время обхода. Важно оставаться спокойным и обрабатывать исключения грамотно:

Java
Скопировать код
try (Stream<Path> stream = Files.walk(Path.of("dir"))) {
    stream.forEach(p -> {
        try {
            System.out.println(p); // О, привет, файл!
        } catch (Exception e) {
            throw new DirectoryIteratorException(new IOException(e));
        }
    });
} catch (DirectoryIteratorException ex) {
    // Мы готовы к этому раскладу
}

Правильная обработка исключений помогает поддерживать чистоту кода и следует best practices в области управления ошибками.

Отдаем предпочтение Path перед File

В Java 8 рекомендуется использовать Path, замещая им File при работе с директориями:

Java
Скопировать код
Path start = Paths.get("dir");
Files.walk(start)
    .filter(Files::isRegularFile)
    .forEach(System.out::println);

Данный подход обеспечивает актуальность кода и соответствие современным рекомендациям Java для операций чтения-записи.

Агрегирование результатов

Порой необходимо собрать все пути во время обхода. Это можно сделать следующим образом:

Java
Скопировать код
List<Path> gatheredPaths = Files.walk(Path.of("dir"))
                               .collect(Collectors.toList());

Наличие в вашем распоряжении List<Path> позволяет осуществлять дополнительные операции, такие как сортировка или фильтрация.

Полезные материалы

  1. Files (Java Platform SE 8) — Официальная документация Java на тему метода Files.walk().
  2. Path (Java Platform SE 8) — Обширная информация об интерфейсе Path.
  3. How to read all files in a folder from Java? – Stack Overflow — Практичный обсуждение на StackOverflow с примерами кода.
  4. FileVisitor (Java Platform SE 8) — Руководство по использованию интерфейса FileVisitor.
  5. DirectoryWalker (Apache Commons IO 2.7 API) — Детали работы с DirectoryWalker в Apache Commons IO.
  6. File I/O (Featuring NIO.2) (The Java™ Tutorials > Essential Java Classes > Basic I/O) — Официальное руководство Oracle по работе с файлами.