Files.newDirectoryStream() 是轻量高效目录遍历方式,支持 glob 模式(如 "*.txt")或自定义 Filter 精确筛选,需 try-with-resources 关闭流,不递归且跨平台大小写需手动处理。

Java 中 Files.newDirectoryStream() 是一种轻量、高效遍历目录的方式,它支持通过过滤器(Filter<Path>)精确筛选文件,比 listFiles() 更灵活,也比全量遍历再过滤更节省资源。
用 glob 模式快速匹配常见后缀
最常用且简洁的方式是使用 glob 语法作为第二个参数。glob 支持通配符,适合按扩展名筛选:
-
"*.txt"匹配当前目录下所有 .txt 文件(不递归) -
"*.jpg,*.png"匹配多个后缀(注意:逗号分隔需用字符串,不是数组) -
"config-*.properties"匹配如config-dev.properties这类命名模式
示例:
try (DirectoryStream<Path> stream = Files.newDirectoryStream(path, "*.log")) {
for (Path entry : stream) {
System.out.println(entry.getFileName());
}
}
用自定义 Filter 精确控制逻辑
当需要更复杂的判断(比如大小、修改时间、是否为普通文件、忽略大小写等),可传入 DirectoryStream.Filter<Path> 实现:
立即学习“Java免费学习笔记(深入)”;
- 必须重写
accept(Path)方法,返回true表示保留该路径 - 注意:
accept()中调用Files.isRegularFile()或Files.size()可能抛出IOException,需在方法内捕获或声明抛出 - 推荐先用
Files.isRegularFile()排除目录,避免后续操作出错
示例(筛选大于 1MB 的 .xml 文件,忽略大小写):
DirectoryStream.Filter<Path> filter = path -> {
try {
return Files.isRegularFile(path) &&
path.toString().toLowerCase().endsWith(".xml") &&
Files.size(path) > 1_048_576;
} catch (IOException e) {
return false; // 出错时跳过该条目
}
};
try (DirectoryStream<Path> stream = Files.newDirectoryStream(dir, filter)) {
// 处理匹配项
}
注意事项和常见陷阱
使用 newDirectoryStream 时容易忽略的关键点:
-
必须显式关闭流:它实现了
AutoCloseable,强烈建议用 try-with-resources,否则可能泄露底层操作系统句柄 - 不递归:只扫描指定目录一层,子目录不会自动进入,需手动递归处理
-
路径有效性不检查:如果传入的目录不存在或无权限,会在创建流时立即抛出
IOException,需提前校验或捕获 -
glob 区分大小写:Windows 默认不区分,Linux/macOS 区分;若需跨平台统一行为,建议用自定义 Filter +
toLowerCase()
结合现代写法提升可读性(Java 8+)
可以用 Lambda 或方法引用简化 Filter,例如只保留普通文件:
Files.newDirectoryStream(dir, Files::isRegularFile)
或者组合多个条件(借助工具方法):
PathMatcher matcher = FileSystems.getDefault().getPathMatcher("glob:**.{java,class}");
Filter<Path> javaOrClass = p -> matcher.matches(p.getFileName());
这样既复用 PathMatcher,又保持逻辑清晰。


















