Java java.nio.file.Files newDirectoryStream() 方法
java.nio.file.Files.newDirectoryStream()
是 Java NIO (New I/O) 包中一个非常实用的方法,用于遍历目录中的文件和子目录。与传统的 java.io.File
相比,它提供了更高效、更灵活的目录遍历方式。
方法定义
public static DirectoryStream<Path> newDirectoryStream(Path dir) throws IOException
public static DirectoryStream<Path> newDirectoryStream(Path dir, String glob) throws IOException
public static DirectoryStream<Path> newDirectoryStream(Path dir, DirectoryStream.Filter<? super Path> filter) throws IOException
public static DirectoryStream<Path> newDirectoryStream(Path dir, String glob) throws IOException
public static DirectoryStream<Path> newDirectoryStream(Path dir, DirectoryStream.Filter<? super Path> filter) throws IOException
参数说明
1. 基本形式参数
dir
(Path 类型):要打开的目录路径- 返回值:
DirectoryStream<Path>
,表示目录中所有条目的迭代流
2. 带过滤器的形式参数
glob
(String 类型):用于匹配文件名的 glob 模式filter
(DirectoryStream.Filter<? super Path> 类型):自定义过滤器接口
使用示例
1. 基本用法:遍历目录
实例
import java.io.IOException;
import java.nio.file.*;
import java.nio.file.attribute.BasicFileAttributes;
public class DirectoryStreamExample {
public static void main(String[] args) {
Path dir = Paths.get("C:/example");
try (DirectoryStream<Path> stream = Files.newDirectoryStream(dir)) {
for (Path file : stream) {
System.out.println(file.getFileName());
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
import java.nio.file.*;
import java.nio.file.attribute.BasicFileAttributes;
public class DirectoryStreamExample {
public static void main(String[] args) {
Path dir = Paths.get("C:/example");
try (DirectoryStream<Path> stream = Files.newDirectoryStream(dir)) {
for (Path file : stream) {
System.out.println(file.getFileName());
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
2. 使用 Glob 模式过滤
实例
// 只列出 .txt 文件
try (DirectoryStream<Path> stream = Files.newDirectoryStream(dir, "*.txt")) {
for (Path file : stream) {
System.out.println(file.getFileName());
}
}
try (DirectoryStream<Path> stream = Files.newDirectoryStream(dir, "*.txt")) {
for (Path file : stream) {
System.out.println(file.getFileName());
}
}
3. 使用自定义过滤器
实例
// 只列出目录
DirectoryStream.Filter<Path> filter = new DirectoryStream.Filter<Path>() {
@Override
public boolean accept(Path entry) throws IOException {
return Files.isDirectory(entry);
}
};
try (DirectoryStream<Path> stream = Files.newDirectoryStream(dir, filter)) {
for (Path file : stream) {
System.out.println(file.getFileName());
}
}
DirectoryStream.Filter<Path> filter = new DirectoryStream.Filter<Path>() {
@Override
public boolean accept(Path entry) throws IOException {
return Files.isDirectory(entry);
}
};
try (DirectoryStream<Path> stream = Files.newDirectoryStream(dir, filter)) {
for (Path file : stream) {
System.out.println(file.getFileName());
}
}
方法特点
1. 高效性
- 使用 NIO 的通道特性,比传统的
File.listFiles()
更高效 - 特别适合处理包含大量文件的目录
2. 资源管理
- 返回的
DirectoryStream
实现了AutoCloseable
接口 - 推荐使用 try-with-resources 语句确保资源被正确释放
3. 线程安全性
- 不是线程安全的,不能在多个线程间共享
- 如果需要并发处理,应该为每个线程创建独立的流
注意事项
- IO 异常处理:必须处理或声明抛出
IOException
- 资源释放:必须关闭流以避免资源泄漏
- 性能考虑:对于非常大的目录,可能需要考虑分批处理
- 符号链接:默认会跟随符号链接,除非特别配置
替代方案比较
方法 | 优点 | 缺点 |
---|---|---|
Files.newDirectoryStream() |
高效,支持过滤 | 非线程安全 |
Files.list() (Java 8+) |
返回 Stream,支持并行处理 | 需要 Java 8+ |
File.listFiles() |
简单易用 | 性能较低 |
最佳实践
- 总是使用 try-with-resources 语句
- 对于复杂过滤逻辑,使用自定义过滤器
- 处理大目录时考虑分批处理
- 在 Java 8+ 环境中,
Files.list()
可能是更好的选择
常见问题解答
Q1: 如何处理隐藏文件?
可以使用自定义过滤器:
实例
DirectoryStream.Filter<Path> filter = entry -> !entry.getFileName().toString().startsWith(".");
Q2: 如何递归遍历子目录?
newDirectoryStream()
本身不递归,可以结合 Files.walkFileTree()
实现递归遍历。
Q3: 性能优化建议是什么?
- 避免在过滤器中进行昂贵的操作
- 对于只读操作,考虑使用
Files.list()
和并行流
通过本文的详细讲解,你应该已经掌握了 Files.newDirectoryStream()
方法的核心用法和最佳实践。这个方法是 Java 文件操作中非常实用的工具,合理使用可以显著提高目录遍历的效率。
点我分享笔记