15.10.2 使用FileVisitor遍历文件和目录

15.10.2 使用FileVisitor遍历文件和目录

在以前的Java版本中,如果程序要遍历指定目录下的所有文件和子目录,则只能使用递归进行遍历,但这种方式不仅复杂,而且灵活性也不高。
有了Files工具类的帮助,现在可以用更优雅的方式来遍历文件和子目录。

walkFileTree方法

Files类提供了如下两个方法来遍历文件和子目录

Files类的walkFileTree方法 描述
static Path walkFileTree(Path start, FileVisitor<? super Path> visitor) 遍历start路径下的所有文件和子目录。
static Path walkFileTree(Path start, Set<FileVisitOption> options, int maxDepth, FileVisitor<? super Path> visitor) 与上一个方法的功能类似。该方法最多遍历maxDepth深度的文件。

文件访问器FileVisitor

上面两个方法都需要FileVisitor参数,FileVisitor代表一个文件访问器,walkFileTree()方法会自动遍历start路径下的所有文件和子目录,遍历文件和子目录都会“触发”FileVisitor中相应的方法。

FileVisitor接口方法

FileVisitor接口中定义了如下4个方法。

FileVisitor方法 描述
FileVisitResult postVisitDirectory(T dir, IOException exc) 访问子目录之后触发该方法
FileVisitResult preVisitDirectory(T dir, BasicFileAttributes attrs) 访问子目录之前触发该方法
FileVisitResult visitFile(T file, BasicFileAttributes attrs) 访问file文件时触发该方法
FileVisitResult visitFileFailed(T file, IOException exc) 访问file文件失败时触发该方法

FileVisitResult枚举

上面4个方法都返回一个FileVisitResult对象,FileVisitResult是一个枚举类,代表了访问之后的后续行为

FileVisitResult枚举值 描述
CONTINUE 代表“继续访问”的后续行为
SKIP_SIBLINGS 代表“继续访问”的后续行为,但不访问该文件或目录的兄弟文件或目录
SKIP_SUBTREE 代表“继续访问”的后续行为,但不访问该文件或目录的子目录树。
TERMINATE 代表“中止访问”的后续行为

SimpleFileVisitor实现类

实际编程时没必要为FileVisitor的4个方法都提供实现,可以通过继承FileVisitor的实现类SimpleFileVisitor来实现自己的“文件访问器”,这样就根据需要、选择性地重写指定方法了。

程序 使用FileVisitor遍历目录 查找指定文件

如下程序示范了使用FileVisitor来遍历文件和子目录。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
import java.io.*;
import java.nio.file.*;
import java.nio.file.attribute.*;

public class FileVisitorTest {
public static void main(String[] args) throws Exception {
// 遍历 G:\Desktop\随书源码\疯狂Java讲义(第4版)光盘\codes\15\ 目录下的所有文件和子目录
Files.walkFileTree(Paths.get("G:", "Desktop", "随书源码", "疯狂Java讲义(第4版)光盘", "codes", "15"),
new SimpleFileVisitor<Path>() {
// 访问文件时候触发该方法
@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs)
throws IOException {
System.out.println("正在访问--文件:" + file);
// 找到了FileInputStreamTest.java文件
if (file.endsWith("FileInputStreamTest.java")) {
System.out.println("--已经找到目标文件--");
// 停止
return FileVisitResult.TERMINATE;
}
// 继续
return FileVisitResult.CONTINUE;
}

// 开始访问目录时触发该方法
@Override
public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs)
throws IOException {
System.out.println("正在访问 路径:" + dir);
// 继续
return FileVisitResult.CONTINUE;
}
});
}
}

上面程序中使用了Files工具类的walkFileTree()方法来遍历G:\Desktop\随书源码\疯狂Java讲义(第4版)光盘\codes\15\目录下的所有文件和子目录,如果找到的文件以“FileInputStreamTest.java”结尾,则程序停止遍历:这就实现了对指定目录进行搜索,直到找到指定文件为止