推荐使用 Files.walk() 遍历目录下所有文件,它简洁安全、支持函数式风格、自动处理符号链接和权限问题;也可用 Files.find() 按条件筛选,或 Files.walkFileTree 实现精细控制。

Java 中遍历目录下所有文件,推荐使用 Files.walk()(Java 8+),它简洁、安全、支持函数式风格,还能自动处理符号链接和权限问题。
用 Files.walk() 递归遍历所有普通文件
这是最常用、最推荐的方式。它返回一个 Stream<path></path>,可配合 filter 筛选文件(排除目录),再用 forEach 处理:
import java.io.IOException;
import java.nio.file.*;
import java.util.stream.Stream;
Path root = Paths.get("/path/to/dir");
try (Stream<Path> paths = Files.walk(root)) {
paths
.filter(Files::isRegularFile) // 只保留普通文件(跳过目录、软链等)
.forEach(System.out::println);
} catch (IOException e) {
e.printStackTrace();
}
注意:Files.walk() 默认会遍历子目录,且不会因权限不足中断(跳过不可访问路径并继续);如需严格报错,可用 Files.walk(root, FileVisitOption.FOLLOW_LINKS) 并捕获异常。
用 Files.find() 按条件筛选(比如特定后缀)
如果只想找 .txt 或 .log 文件,Files.find() 更直接,支持自定义谓词(Predicate):
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
立即学习“Java免费学习笔记(深入)”;
try (Stream<Path> files = Files.find(
root,
Integer.MAX_VALUE, // 最大深度(Integer.MAX_VALUE 表示无限深)
(path, attrs) -> attrs.isRegularFile() && path.toString().endsWith(".log")
)) {
files.forEach(System.out::println);
}
优点是把路径判断逻辑写在访问时,避免先生成再过滤,内存更友好;attrs 还能快速获取大小、修改时间等,无需额外调用 Files.size() 等。
传统方式:Files.walkFileTree(适合复杂控制)
当需要精细控制(如遇到错误时记录、跳过某些目录、统计文件类型数量),用 SimpleFileVisitor 更灵活:
- 重写
visitFile()处理每个文件 - 重写
preVisitDirectory()判断是否进入某子目录(比如跳过target/或.git/) - 重写
visitFileFailed()处理无权限等异常
示例:跳过名为 node_modules 的目录:
Files.walkFileTree(root, new SimpleFileVisitor<Path>() {
@Override
public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) {
if ("node_modules".equals(dir.getFileName().toString())) {
return FileVisitResult.SKIP_SUBTREE;
}
return FileVisitResult.CONTINUE;
}
@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) {
System.out.println("File: " + file);
return FileVisitResult.CONTINUE;
}
});
注意事项与避坑点
- 别用 File.list() / File.listFiles() 递归:不支持符号链接、易出 NullPointerException、无法处理权限异常,且 Java 7 后已不推荐
- 务必关闭 Stream:用 try-with-resources,否则可能泄露文件句柄(尤其在 Windows 上)
- 路径编码:确保传入的
Path使用 UTF-8 字符串构造,避免中文路径乱码 - 性能提示:如果只查一层(非递归),用
Files.list(root)更快,它不深入子目录

















