使用 Files.walk 遍历目录树
使用 Files.walk 递归列出文件、按扩展名筛选,并计算目录大小
使用 Files.walk 遍历目录树 是 CoddyKit 上的免费 Java Academy 课时。 这是第 3 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 Java Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 Java Academy 课程共包含 4 节课。
Files.walk 概览
Files.walk(startPath) 返回惰性的 Stream<Path>,从给定路径开始递归列出所有文件和目录。它采用深度优先遍历,并包含起始路径本身。
import java.nio.file.*;
import java.util.stream.*;
try (Stream<Path> stream = Files.walk(Path.of("/home/user/projects"))) {
stream.forEach(System.out::println);
} // stream and underlying resources closed automatically限制深度
提供最大深度以防止递归过深:
Path root = Path.of("/home/user/projects");
// Only immediate children (depth 1)
try (var stream = Files.walk(root, 1)) {
stream.filter(p -> !p.equals(root)) // exclude start path
.forEach(System.out::println);
}按文件类型筛选
结合 Files.isRegularFile() 或 Files.isDirectory() 进行筛选:
Path root = Path.of(".");
try (var stream = Files.walk(root)) {
long fileCount = stream
.filter(Files::isRegularFile)
.count();
System.out.println("Files: " + fileCount);
}按扩展名筛选
查找具有特定扩展名的所有文件:
try (var stream = Files.walk(Path.of("/src"))) {
List<Path> javaFiles = stream
.filter(Files::isRegularFile)
.filter(p -> p.toString().endsWith(".java"))
.collect(Collectors.toList());
javaFiles.forEach(System.out::println);
}计算目录大小
对目录下所有文件的大小求和:
try (var stream = Files.walk(Path.of("/home/user/data"))) {
long totalBytes = stream
.filter(Files::isRegularFile)
.mapToLong(p -> {
try { return Files.size(p); }
catch (IOException e) { return 0; }
})
.sum();
System.out.printf("Total: %.2f MB%n", totalBytes / 1_048_576.0);
}Files.list 与 Files.walk
Files.list(dir) 只列出单个目录的直接内容(类似于 ls)。Files.walk 会递归进入子目录。
// Only immediate children:
try (var stream = Files.list(Path.of("/home/user"))) {
stream.forEach(System.out::println);
}使用 Files.find 进行基于属性的搜索
当根据文件属性进行匹配时,Files.find(root, depth, matcher) 比 walk+filter 更高效:
import java.nio.file.attribute.BasicFileAttributes;
try (var stream = Files.find(
Path.of("/home/user"),
Integer.MAX_VALUE,
(p, attrs) -> attrs.isRegularFile() && attrs.size() > 1_000_000
)) {
stream.forEach(p -> System.out.println("Large file: " + p));
}删除目录树
使用 walk + sorted(reversed) 删除目录及其全部内容(先删除最深处的文件):
Path toDelete = Path.of("/tmp/workdir");
try (var stream = Files.walk(toDelete)) {
stream.sorted(Comparator.reverseOrder())
.forEach(p -> {
try { Files.delete(p); }
catch (IOException e) { e.printStackTrace(); }
});
}复制目录树
遍历源目录树并复制每个文件,同时保留目录结构:
Path src = Path.of("/source"), dst = Path.of("/destination");
try (var stream = Files.walk(src)) {
stream.forEach(p -> {
try {
Path target = dst.resolve(src.relativize(p));
if (Files.isDirectory(p)) Files.createDirectories(target);
else Files.copy(p, target, StandardCopyOption.REPLACE_EXISTING);
} catch (IOException e) { throw new RuntimeException(e); }
});
}处理无法访问的文件
如果遇到无法读取的目录,Files.walk 会抛出 IOException。请谨慎使用 FileVisitOption.FOLLOW_LINKS——符号链接循环可能导致无限递归。
try (var stream = Files.walk(Path.of("/"),
FileVisitOption.FOLLOW_LINKS)) { // caution: symlink loops
// ...
} catch (IOException e) {
System.err.println("Access error: " + e.getMessage());
}walkFileTree:基于事件的遍历
如需更精细的控制(访问前、访问后和错误处理),请将 Files.walkFileTree() 与 FileVisitor 一起使用:
Files.walkFileTree(Path.of("/home/user"), new SimpleFileVisitor<Path>() {
@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) {
System.out.println("File: " + file);
return FileVisitResult.CONTINUE;
}
@Override
public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) {
System.out.println("Dir: " + dir);
return FileVisitResult.CONTINUE;
}
});快速检查
如果只想列出目录的直接子项(不递归),应使用哪个 Files 方法?
回顾:Files.walk
要点:
- Files.walk(root)——递归产生所有路径的惰性 Stream
- 始终使用资源自动关闭结构来关闭流
- 使用 Files.isRegularFile/isDirectory 进行筛选;使用 endsWith 按扩展名筛选
- Files.list(dir)——仅列出直接子项
- Files.find——高效的基于属性的搜索
- walkFileTree——基于事件,并提供访问前/访问后的回调
常见问题解答
「使用 Files.walk 遍历目录树」课时是免费的吗?
是的 — 「使用 Files.walk 遍历目录树」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 Java Academy 课程的其余内容,请升级到 CoddyKit PRO。 Java Academy 课程共包含 4 节课。
「使用 Files.walk 遍历目录树」这节课中我会学到什么?
使用 Files.walk 递归列出文件、按扩展名筛选,并计算目录大小 你通过在浏览器中直接运行的动手代码来练习 Java Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。
学习 Java Academy 需要有经验吗?
无需任何先前经验。CoddyKit 上的 Java Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 3 节课,共 4 节。
「使用 Files.walk 遍历目录树」课时需要多长时间?
大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。
我能在这节 Java Academy 课中编写并运行代码吗?
能。每节 Java Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。
此课程中的所有课时
- Path:表示文件位置
- Files 工具:读取、写入、复制与移动
- 使用 Files.walk 遍历目录树
- WatchService:监控文件变化