Java java.nio.file.Files newDirectoryStream() 方法

Java File Java java.nio.file.Files


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

参数说明

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();
        }
    }
}

2. 使用 Glob 模式过滤

实例

// 只列出 .txt 文件
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());
    }
}

方法特点

1. 高效性

  • 使用 NIO 的通道特性,比传统的 File.listFiles() 更高效
  • 特别适合处理包含大量文件的目录

2. 资源管理

  • 返回的 DirectoryStream 实现了 AutoCloseable 接口
  • 推荐使用 try-with-resources 语句确保资源被正确释放

3. 线程安全性

  • 不是线程安全的,不能在多个线程间共享
  • 如果需要并发处理,应该为每个线程创建独立的流

注意事项

  1. IO 异常处理:必须处理或声明抛出 IOException
  2. 资源释放:必须关闭流以避免资源泄漏
  3. 性能考虑:对于非常大的目录,可能需要考虑分批处理
  4. 符号链接:默认会跟随符号链接,除非特别配置

替代方案比较

方法 优点 缺点
Files.newDirectoryStream() 高效,支持过滤 非线程安全
Files.list() (Java 8+) 返回 Stream,支持并行处理 需要 Java 8+
File.listFiles() 简单易用 性能较低

最佳实践

  1. 总是使用 try-with-resources 语句
  2. 对于复杂过滤逻辑,使用自定义过滤器
  3. 处理大目录时考虑分批处理
  4. 在 Java 8+ 环境中,Files.list() 可能是更好的选择

常见问题解答

Q1: 如何处理隐藏文件?

可以使用自定义过滤器:

实例

DirectoryStream.Filter<Path> filter = entry -> !entry.getFileName().toString().startsWith(".");

Q2: 如何递归遍历子目录?

newDirectoryStream() 本身不递归,可以结合 Files.walkFileTree() 实现递归遍历。

Q3: 性能优化建议是什么?

  • 避免在过滤器中进行昂贵的操作
  • 对于只读操作,考虑使用 Files.list() 和并行流

通过本文的详细讲解,你应该已经掌握了 Files.newDirectoryStream() 方法的核心用法和最佳实践。这个方法是 Java 文件操作中非常实用的工具,合理使用可以显著提高目录遍历的效率。

Java File Java java.nio.file.Files