更快地获取大型目录内容(java.io.File 替代项)

2022-09-03 04:59:21

我已经使用旧的,过时的java.io.File.listFiles()太久了。

性能不太好。是的:

  • 成本高昂,因为它为每个条目创建一个新的 File 对象。
  • 速度很慢,因为您必须等待数组完成才能开始处理。
  • 非常糟糕,特别是如果你只需要处理内容的子集。

有哪些替代方案?


答案 1

Java 7的java.nio.file包可以用来增强性能。

迭代器

目录流<T>接口可用于循环访问目录,而无需将其内容预加载到内存中。虽然旧 API 在文件夹中创建一个包含所有文件名的数组,但新方法会在迭代期间遇到每个文件名(或有限大小的缓存文件名组)时加载它。

若要获取表示给定路径的实例,可以调用 Files.newDirectoryStream(Path) 静态方法。我建议你使用 try-with-resources 语句来正确关闭流,但如果不能,请记住在最后使用 DirectoryStream<T>.close() 手动执行此操作。

Path folder = Paths.get("...");
try (DirectoryStream<Path> stream = Files.newDirectoryStream(folder)) {
    for (Path entry : stream) {
        // Process the entry
    }
} catch (IOException ex) {
    // An I/O problem has occurred
}

过滤 器

DirectoryStream.Filter<T>接口可用于在迭代期间跳过条目组。

由于它是一个@FunctionalInterface,从Java 8开始,您可以使用lambda表达式实现它,覆盖Filter<T>.accept(T)方法,该方法决定是否应接受或过滤给定的目录条目。然后,您将对新创建的实例使用 Files.newDirectoryStream(Path, DirectoryStream.Filter<? super Path>) 静态方法。或者,您可能更喜欢 Files.newDirectoryStream(Path, String) 静态方法,该方法可用于简单的文件名匹配。

Path folder = Paths.get("...");
try (DirectoryStream<Path> stream = Files.newDirectoryStream(folder, "*.txt")) {
    for (Path entry : stream) {
        // The entry can only be a text file
    }
} catch (IOException ex) {
    // An I/O problem has occurred
}

Path folder = Paths.get("...");
try (DirectoryStream<Path> stream = Files.newDirectoryStream(folder,
        entry -> Files.isDirectory(entry))) {
    for (Path entry : stream) {
        // The entry can only be a directory
    }
} catch (IOException ex) {
    // An I/O problem has occurred
}

答案 2