Java中遍历目录树最推荐Files.walk(),它简洁安全、支持流式处理且自动处理符号链接和异常;其次可用Files.find()按条件高效查找,或用Files.walkFileTree()实现自定义逻辑。

Java 中遍历目录树最推荐的方式是使用 Files.walk()(Java 8+),它简洁、安全、支持流式处理,还能自动处理符号链接和异常。
用 Files.walk() 遍历所有文件和子目录
这是最常用也最稳妥的方法。它返回一个 Stream<path></path>,可配合 filter、forEach 等操作:
try (Stream<Path> stream = Files.walk(Paths.get("/home/user/docs"))) {
stream.filter(Files::isRegularFile)
.forEach(System.out::println);
}
- 默认深度优先、递归遍历整个子树
- 加
try-with-resources可确保资源及时释放(尤其大目录) - 用
Files.isRegularFile()或Files.isDirectory()过滤类型 - 若只想遍历固定深度,可传入第二个参数:
Files.walk(path, 2)表示最多下探 2 层
用 Files.find() 按条件查找
适合带谓词筛选的场景,比如找所有 .java 文件:
try (Stream<Path> stream = Files.find(
Paths.get("/src"),
Integer.MAX_VALUE,
(path, attrs) -> path.toString().endsWith(".java")
)) {
stream.forEach(System.out::println);
}
- 第三个参数是
BiPredicate<path basicfileattributes></path>,可同时访问路径和文件属性 - 第二个参数控制最大深度,设为
Integer.MAX_VALUE表示不限深度 - 比先 walk 再 filter 更高效(底层可提前剪枝)
用 Files.walkFileTree() 实现自定义逻辑
需要精细控制(如跳过某些目录、统计大小、捕获异常)时用这个:
立即学习“Java免费学习笔记(深入)”;
Files.walkFileTree(Paths.get("/data"), new SimpleFileVisitor<Path>() {
@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) {
if (file.toString().endsWith(".log")) {
System.out.println("Found log: " + file);
}
return FileVisitResult.CONTINUE;
}
@Override
public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) {
// 可在此返回 SKIP_SUBTREE 跳过该目录
return Files.isWritable(dir) ? CONTINUE : SKIP_SUBTREE;
}
});
-
SimpleFileVisitor提供了默认空实现,只需重写关心的方法 -
visitFileFailed()可捕获权限不足等异常,避免遍历中断 - 适合需状态累积(如总行数、最大文件)、或需中断/跳过的复杂场景
注意点和常见坑
- 不要用递归调用 listFiles():易栈溢出、不处理符号链接、无法统一异常处理
- 遍历时遇到权限拒绝或 I/O 错误,默认会抛异常;用
walkFileTree可在visitFileFailed中处理 - 路径含中文或特殊字符时,确保 JVM 使用 UTF-8(通常默认已是),无需额外编码转换
- 大目录建议用 Stream + limit() 或分批处理,避免内存积压


















