7.4 文件系统的搜索

问题

用户希望查找文件树中满足给定属性的文件。

方案

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

讨论

find 方法的签名如下:

  1. public static Stream<Path> find(Path start,
  2. int maxDepth,
  3. BiPredicate<Path, BasicFileAttributes> matcher,
  4. FileVisitOption... options)
  5. throws IOException

可以看到,find 方法的签名与 walk 方法类似,但增加了一个用于决定是否应返回特定 Path 的匹配器 BiPredicatefind 方法从给定路径开始执行深度优先搜索(depth-first search),直至达到 maxDepth 指定的目录级别。对于每条路径,find 方法都会调用 BiPredicate 进行评估。如果指定为 FileVisitOption 枚举的值,则执行后面的链接。

BiPredicate 需要根据每个路径元素及其关联的 BasicFileAttributes 对象返回布尔值。如例 7-8 所示,程序将返回 fileio 包(参见本书配套源代码)中所有非目录文件的路径。

例 7-8 查找 fileio 包中的非目录文件

  1. try (Stream<Path> paths =
  2. Files.find(Paths.get("src/main/java"), Integer.MAX_VALUE,
  3. (path, attributes) ->
  4. !attributes.isDirectory() && path.toString().contains("fileio"))) {
  5. paths.forEach(System.out::println);
  6. } catch (IOException e) {
  7. e.printStackTrace();
  8. }

输出结果如下:

  1. src/main/java/fileio/FileList.java
  2. src/main/java/fileio/ProcessDictionary.java
  3. src/main/java/fileio/SearchForFiles.java
  4. src/main/java/fileio/WalkTheTree.java

对于遍历文件树时遇到的每一个文件,find 方法都会根据给定的 BiPredicate 进行评估,类似于在 walk 方法返回的 Stream 上调用筛选器。不过,Javadoc 认为 find 方法避免了对 BasicFileAttributes 对象的冗余检索,因而能提高程序的效率。

类似地,由于返回的 Stream 封装了 DirectoryStream,在关闭流的同时,底层数据源也随之关闭。有鉴于此,在 try-with-resources 代码块中使用 find 方法是首选方案。

另见

有关文件系统的遍历请参见范例 7.3。