Как выполнить итерацию файлов в каталоге в Java?

Мне нужно получить список всех файлов в каталоге, включая файлы во всех подкаталогах. Каков стандартный способ выполнения итерации каталогов с помощью Java?

Ответ 1

Вы можете использовать File#isDirectory(), чтобы проверить, является ли данный файл (путь) каталогом. Если это true, вы снова вызываете тот же метод с его результатом File#listFiles(). Это называется recursion.

Вот пример основного запуска.

public static void main(String... args) {
    File[] files = new File("C:/").listFiles();
    showFiles(files);
}

public static void showFiles(File[] files) {
    for (File file : files) {
        if (file.isDirectory()) {
            System.out.println("Directory: " + file.getName());
            showFiles(file.listFiles()); // Calls same method again.
        } else {
            System.out.println("File: " + file.getName());
        }
    }
}

Обратите внимание, что это чувствительно к StackOverflowError, когда дерево глубже, чем может хранить стек JVM. Вместо этого вы можете использовать итеративный подход или tail-recursion, но этот другой объект;)

Ответ 2

Если вы используете Java 1.7, вы можете использовать java.nio.file.Files.walkFileTree(...).

Например:

public class WalkFileTreeExample {

  public static void main(String[] args) {
    Path p = Paths.get("/usr");
    FileVisitor<Path> fv = new SimpleFileVisitor<Path>() {
      @Override
      public FileVisitResult visitFile(Path file, BasicFileAttributes attrs)
          throws IOException {
        System.out.println(file);
        return FileVisitResult.CONTINUE;
      }
    };

    try {
      Files.walkFileTree(p, fv);
    } catch (IOException e) {
      e.printStackTrace();
    }
  }

}

Если вы используете Java 8, вы можете использовать потоковый интерфейс с java.nio.file.Files.walk(...):

public class WalkFileTreeExample {

  public static void main(String[] args) {
    try (Stream<Path> paths = Files.walk(Paths.get("/usr"))) {
      paths.forEach(System.out::println);
    } catch (IOException e) {
      e.printStackTrace();
    }
  }

}

Ответ 3

Посмотрите FileUtils класс в Apache Commons - в частности iterateFiles:

Разрешает итерацию по файлам в заданной директории (и, возможно, ее подкаталоги).

Ответ 4

Используя org.apache.commons.io.FileUtils

File file = new File("F:/Lines");       
Collection<File> files = FileUtils.listFiles(file, null, true);     
for(File file2 : files){
    System.out.println(file2.getName());            
} 

Используйте false, если вы не хотите файлы из подкаталогов.

Ответ 5

Для Java 7+ существует также https://docs.oracle.com/javase/7/docs/api/java/nio/file/DirectoryStream.html

Пример, взятый из Javadoc:

List<Path> listSourceFiles(Path dir) throws IOException {
   List<Path> result = new ArrayList<>();
   try (DirectoryStream<Path> stream = Files.newDirectoryStream(dir, "*.{c,h,cpp,hpp,java}")) {
       for (Path entry: stream) {
           result.add(entry);
       }
   } catch (DirectoryIteratorException ex) {
       // I/O error encounted during the iteration, the cause is an IOException
       throw ex.getCause();
   }
   return result;
}

Ответ 6

Это дерево, поэтому рекурсия - ваш друг: начните с родительского каталога и вызовите метод, чтобы получить массив дочерних файлов. Итерация через дочерний массив. Если текущее значение является каталогом, передайте его рекурсивному вызову вашего метода. Если нет, обработайте файл листа соответствующим образом.

Ответ 7

Как уже отмечалось, это проблема рекурсии. В частности, вы можете посмотреть

listFiles() 

В java File API здесь. Он возвращает массив всех файлов в каталоге. Используя это вместе с

isDirectory()

чтобы увидеть, нужно ли вам снова записаться, - это хорошее начало.

Ответ 8

Чтобы добавить с ответом @msandiford, как и в большинстве случаев, когда идет дерево файлов, вы можете выполнить функцию как каталог или какой-либо конкретный файл. Если u неохотно использует потоки. Можно переопределить следующие методы:

Files.walkFileTree(Paths.get(Krawl.INDEXPATH), EnumSet.of(FileVisitOption.FOLLOW_LINKS), Integer.MAX_VALUE,
    new SimpleFileVisitor<Path>() {
        @Override
        public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs)
                throws IOException {
                // Do someting before directory visit
                return FileVisitResult.CONTINUE;
        }
        @Override
        public FileVisitResult visitFile(Path file, BasicFileAttributes attrs)
                throws IOException {
                // Do something when a file is visited
                return FileVisitResult.CONTINUE;
        }
        @Override
        public FileVisitResult postVisitDirectory(Path dir, IOException exc)
                throws IOException {
                // Do Something after directory visit 
                return FileVisitResult.CONTINUE;
        }
});

Ответ 9

Вы также можете использовать File.list(FilenameFilter) (и варианты) для обхода файла. Сокращенный код и работает в ранних версиях Java, например:

// list files in dir
new File(dir).list(new FilenameFilter() {
    public boolean accept(File dir, String name) {
        String file = dir.getAbsolutePath() + File.separator + name;
        System.out.println(file);
        return false;
    }
});