使用 Java 以递归方式列出目录中的所有文件

2022-08-31 10:47:25

我有这个函数,它以递归方式打印目录中所有文件的名称。问题是我的代码非常慢,因为它必须在每次迭代时访问远程网络设备。

我的计划是首先以递归方式从目录中加载所有文件,然后使用正则表达式浏览所有文件,以过滤掉所有我不想要的文件。有人有更好的建议吗?

public static printFnames(String sDir) {
    File[] faFiles = new File(sDir).listFiles();
    for (File file : faFiles) {
        if (file.getName().matches("^(.*?)")) {
            System.out.println(file.getAbsolutePath());
        }
        if (file.isDirectory()) {
            printFnames(file.getAbsolutePath());
        }
    }
}

这只是稍后的测试,我不会使用这样的代码,而是将每个与高级正则表达式匹配的文件的路径和修改日期添加到数组中。


答案 1

假设这是你将要编写的实际生产代码,那么我建议使用已经解决的这类问题的解决方案 - Apache Commons IO,特别是FileUtils.listFiles()。它处理嵌套目录,过滤器(基于名称,修改时间等)。

例如,对于正则表达式:

Collection files = FileUtils.listFiles(
  dir, 
  new RegexFileFilter("^(.*?)"), 
  DirectoryFileFilter.DIRECTORY
);

这将以递归方式搜索与正则表达式匹配的文件,并将结果作为集合返回。^(.*?)

值得注意的是,这不会比滚动自己的代码更快,它正在做同样的事情 - 在Java中拖网文件系统只是很慢。不同之处在于,Apache Commons版本中没有错误。


答案 2

在Java 8中,它是一个1行,通过Files.find()具有任意大的深度(例如)和isRegularFile()BasicFileAttributes999

public static printFnames(String sDir) {
    Files.find(Paths.get(sDir), 999, (p, bfa) -> bfa.isRegularFile()).forEach(System.out::println);
}

要添加更多过滤,请增强 lambda,例如,在过去 24 小时内修改的所有 jpg 文件:

(p, bfa) -> bfa.isRegularFile()
  && p.getFileName().toString().matches(".*\\.jpg")
  && bfa.lastModifiedTime().toMillis() > System.currentMillis() - 86400000