7.2 以流的形式检索文件

问题

用户希望将目录中的所有文件作为 Stream 进行处理。

方案

使用 java.nio.file.Files 类定义的静态方法 list

讨论

list 方法传入 Path 作为参数,并返回一个包装 DirectoryStream4 的 Stream。由于 DirectoryStream 接口继承自 AutoCloseabletry-with-resources 构造是使用 list 方法的最佳方式,如例 7-6 所示。

4这是一个 IO 流而非函数式流。

例 7-6 Files.list(path) 方法的应用

  1. try (Stream<Path> list = Files.list(Paths.get("src/main/java"))) {
  2. list.forEach(System.out::println);
  3. } catch (IOException e) {
  4. e.printStackTrace();
  5. }

如果在具有标准 Maven 或 Gradle 结构的项目根目录下执行上述代码,程序将打印 src/ main/java 目录中所有文件和文件夹的名称。使用 try-with-resources 代码块,当 try 代码块执行完毕后,系统将在 Stream 上调用 close 方法,然后在底层 DirectoryStream 上调用 close 方法。请注意,目录和文件不是递归的。

执行本书配套的源代码(例 7-6),程序将输出目录和单个文件:

  1. src/main/java/collectors
  2. src/main/java/concurrency
  3. src/main/java/datetime
  4. ...
  5. src/main/java/Summarizing.java
  6. src/main/java/tasks
  7. src/main/java/UseFilenameFilter.java

list 方法的签名如下,其返回类型为 Stream,参数为目录的路径:

  1. public static Stream<Path> list(Path dir) throws IOException

请注意,对非目录资源执行 list 方法将抛出 NotDirectoryException

Javadoc 指出,list 方法返回的流具备弱一致性(weak consistency)。换言之,“流是线程安全的,但在迭代时不会冻结目录,因此它可能会(也可能不会)反映 list 方法返回后所发生的目录更新”。

另见

有关采用深度优先搜索遍历文件系统的讨论请参见范例 7.3。