我如何递归地列出在Java目录下的所有文件?框架是否提供任何实用程序?

我看到了很多俗气的实现。但没有来自框架或nio


当前回答

FileUtils有iterateFiles和listFiles方法。试一试吧。(从commons-io)

编辑:您可以在这里查看不同方法的基准测试。common -io方法似乎很慢,所以从这里选择一些更快的方法(如果重要的话)

其他回答

我认为这应该是可行的:

File dir = new File(dirname);
String[] files = dir.list();

这样你就有文件和dirs了。现在使用递归并对dirs(文件类具有isDirectory()方法)执行相同的操作。

这段代码可以运行了

public static void main(String... args) {
    File[] files = new File("D:/").listFiles();
    if (files != null) 
       getFiles(files);
}

public static void getFiles(File[] files) {
    for (File file : files) {
        if (file.isDirectory()) {
            getFiles(file.listFiles());
        } else {
            System.out.println("File: " + file);
        }
    }
}

对于这种简单的转换,我更喜欢使用队列而不是递归:

List<File> allFiles = new ArrayList<File>();
Queue<File> dirs = new LinkedList<File>();
dirs.add(new File("/start/dir/"));
while (!dirs.isEmpty()) {
  for (File f : dirs.poll().listFiles()) {
    if (f.isDirectory()) {
      dirs.add(f);
    } else if (f.isFile()) {
      allFiles.add(f);
    }
  }
}

Kotlin为此使用了FileTreeWalk。例如:

dataDir.walkTopDown().filter { !it.isDirectory }.joinToString("\n") {
   "${it.toRelativeString(dataDir)}: ${it.length()}"
}

将生成给定根下所有非目录文件的文本列表,每行一个文件,其路径相对于根和长度。

Java 8提供了一个很好的流来处理树中的所有文件。

try (Stream<Path> stream = Files.walk(Paths.get(path))) {
    stream.filter(Files::isRegularFile)
          .forEach(System.out::println);
}

这提供了一种自然的遍历文件的方法。因为它是一个流,你可以对结果做所有漂亮的流操作,如限制,分组,映射,退出等。

更新:我可能会指出还有文件。find使用一个BiPredicate,如果需要检查文件属性,这可能更有效。

Files.find(Paths.get(path),
           Integer.MAX_VALUE,
           (filePath, fileAttr) -> fileAttr.isRegularFile())
        .forEach(System.out::println);

注意,虽然JavaDoc回避了这个方法可能比Files更有效。Walk实际上是相同的,如果您也在过滤器中检索文件属性,则可以观察到性能上的差异。最后,如果需要筛选属性,请使用Files。find,否则使用Files。步行,主要是因为交通超载,而且更方便。

测试:根据要求,我提供了许多答案的性能比较。查看包含结果和测试用例的Github项目。