Java核心技术·卷Ⅱ:高级特性(原书第10版)
上QQ阅读APP看书,第一时间看更新

2.5.7 使用目录流

正如在前一节中所看到的,Files.walk方法会产生一个可以遍历目录中所有子孙的Stream<Path>对象。有时,你需要对遍历过程进行更加细粒度的控制。在这种情况下,应该使用File.newDirectoryStream对象,它会产生一个DirectoryStream。注意,它不是java.util.stream.Stream的子接口,而是专门用于目录遍历的接口。它是Iterable的子接口,因此你可以在增强的for循环中使用目录流。下面是其使用模式:

try语句块用来确保目录流可以被正确关闭。访问目录中的项并没有具体的顺序。

可以用glob模式来过滤文件:

表2-4展示了所有的glob模式。

表2-4 Glob模式

警告:如果使用Windows的glob语法,则必须对反斜杠转义两次:一次为glob语法转义,一次为Java字符串转义:Files.newDirectoryStream(dir,“C:\\\\”)

如果想要访问某个目录的所有子孙成员,可以转而调用walkFileTree方法,并向其传递一个FileVisitor类型的对象,这个对象会得到下列通知:

·在遇到一个文件或目录时:FileVisitResult visitFile(T path,BasicFileAttributes attrs)

·在一个目录被处理前:FileVisitResult preVisitDirectory(T dir,IOException ex)

·在一个目录被处理后:FileVisitResult postVisitDirectory(T dir,IOException ex)

·在试图访问文件或目录时发生错误,例如没有权限打开目录:FileVisitResult visitFileFailed(path,IOException)

对于上述每种情况,都可以指定是否希望执行下面的操作:

·继续访问下一个文件:FileVisitResult.CONTINUE

·继续访问,但是不再访问这个目录下的任何项了:FileVisitResult.SKIP_SUBTREE

·继续访问,但是不再访问这个文件的兄弟文(和该文件在同一个目录下的文件)了:FileVisitResult.SKIP_SIBLINGS

·终止访问:FileVisitResult.TERMINATE

当有任何方法抛出异常时,就会终止访问,而这个异常会从walkFileTree方法中抛出。

注意:FileVisitor接口是泛化类型,但是你也太可能会使用除FileVisitor<Path>之外的东西。walkFileTree方法可以接受FileVisitor<?Super Path>类型的参数,但是Path并没有多少超类型。

便捷类SimpleFileVisitor实现了FileVisitor接口,但是其除visitFileFailed方法之外的所有方法并不做任何处理而是直接继续访问,而visitFileFailed方法会抛出由失败导致的异常,并进而终止访问。

例如,下面的代码展示了如何打印出给定目录下的所有子目录:

值得注意的是,我们需要覆盖postVisitDirectory方法和visitFileFailed方法,否则,访问会在遇到不允许打开的目录或不允许访问的文件时立即失败。

还应该注意的是,路径的众多属性是作为preVisitDirectory和visitFile方法的参数传递的。访问者不得不通过操作系统调用来获得这些属性,因为它需要区分文件和目录。因此,你就不需要再次执行系统调用了。

如果你需要在进入或离开一个目录时执行某些操作,那么FileVisitor接口的其他方法就显得非常有用了。例如,在删除目录树时,需要在移除当前目录的所有文件之后,才能移除该目录。下面是删除目录树的完整代码:

java.nio.File.Files7

·static DirectoryStream<Path>newDirectoryStream(Path path)

·static DirectoryStream<Path>newDirectoryStream(Path path,String glob)

获取给定目录中可以遍历所有文件和目录的迭代器。第二个方法只接受那些与给定的glob模式匹配的项。

·static Path walkFileTree(Path start,FileVisitor<?super Path>visitor)

遍历给定路径的所有子孙,并将访问器应用于这些子孙之上。

java.nio.file.SimpleFileVisitor<T>7

·static FileVisitResult visitFile(T path,BasicFileAttributes attrs)

在访问文件或目录时被调用,返回CONTINUE、SKIP_SUBTREE、SKIP_SIBLINGS和TERMINATE之一,默认实现是不做任何操作而继续访问。

·static FileVisitResult preVisitDirectory(T dir,BasicFileAttributes attrs)

·static FileVisitResult postVisitDirectory(T dir,BasicFileAttributes attrs)

在访问目录之前和之后被调用,默认实现是不做任何操作而继续访问。

·static FileVisitResult visitFileFailed(T path,IOException exc)

如果在试图获取给定文件的信息时抛出异常,则该方法被调用。默认实现是重新抛出异常,这会导致访问操作以这个异常而终止。如果你想自己访问,可以覆盖这个方法。