Skip to content

Path 和 Files 工具类

JDK 7 引入了 PathFiles,是对 File 类的现代化替代。

这一节讲清楚它们的新增 API 和改进之处。

Path:更现代的路径表示

创建 Path

java
// 方式 1:Path.of()(JDK 11+)
Path p1 = Path.of("dir/subdir/file.txt");
Path p2 = Path.of("dir", "subdir", "file.txt");

// 方式 2:Paths.get()
Path p3 = Paths.get("dir", "subdir", "file.txt");

// 方式 3:从 File 转换
Path p4 = new File("test.txt").toPath();
File f = p4.toFile();

路径操作

java
Path p = Path.of("dir/subdir/file.txt");
p.getFileName();       // "file.txt"
p.getParent();         // "dir/subdir"
p.getRoot();           // "/"(Linux/macOS)或 "C:\\"(Windows)
p.isAbsolute();        // false
p.toAbsolutePath();     // 绝对路径
p.getNameCount();      // 3(路径段数)
p.getName(0);         // "dir"
p.getName(1);         // "subdir"
p.getName(2);         // "file.txt"
p.subpath(1, 3);      // "subdir/file.txt"

路径解析

java
Path p = Path.of("dir/subdir/file.txt");

// 拼接
Path resolved = p.resolve("sibling.txt"); // "dir/subdir/sibling.txt"
Path resolved2 = p.resolveSibling("other.txt"); // "dir/other.txt"

// 相对路径
Path p1 = Path.of("dir/file.txt");
Path p2 = Path.of("dir/sub/file2.txt");
Path relative = p2.relativize(p1); // "../file.txt"

// 规范化
Path normalized = Path.of("dir/../dir/file.txt").normalize(); // "dir/file.txt"

Files:文件工具类

Files 是 NIO 的核心工具类,提供大量静态方法。

判断方法

java
Files.exists(path);              // 是否存在
Files.notExists(path);         // 是否不存在
Files.isRegularFile(path);     // 是否是普通文件
Files.isDirectory(path);       // 是否是目录
Files.isSymbolicLink(path);    // 是否是符号链接
Files.isReadable(path);         // 是否可读
Files.isWritable(path);         // 是否可写
Files.isExecutable(path);      // 是否可执行

读取文件

java
// 读取全部(一次性读入内存,适合小文件)
byte[] bytes = Files.readAllBytes(Path.of("file.bin"));

String content = Files.readString(Path.of("file.txt")); // JDK 11+,默认 UTF-8
String content = Files.readString(Path.of("file.txt"), StandardCharsets.UTF_8);

// 按行读取
List<String> lines = Files.readAllLines(Path.of("file.txt"), StandardCharsets.UTF_8);

// 流式处理行(大文件)
try (Stream<String> stream = Files.lines(Path.of("file.txt"))) {
    stream.filter(line -> line.length() > 10)
          .forEach(System.out::println);
}

写入文件

java
// 写入字节数组或字符串
Files.write(Path.of("out.txt"), "hello".getBytes());
Files.writeString(Path.of("out.txt"), "hello"); // JDK 11+

// 追加模式
Files.write(Path.of("out.txt"), "append".getBytes(),
    StandardOpenOption.APPEND);

// 写入多行
List<String> lines = List.of("第一行", "第二行");
Files.write(Path.of("out.txt"), lines, StandardCharsets.UTF_8);

// 逐行写入
try (BufferedWriter writer = Files.newBufferedWriter(Path.of("out.txt"))) {
    for (String line : lines) {
        writer.write(line);
        writer.newLine();
    }
}

创建与删除

java
// 创建文件
Files.createFile(Path.of("new.txt"));

// 创建目录
Files.createDirectory(Path.of("mydir"));         // 单层
Files.createDirectories(Path.of("a/b/c"));          // 多层

// 删除
Files.delete(Path.of("file.txt"));                 // 不存在抛异常
Files.deleteIfExists(Path.of("file.txt"));          // 不存在不抛异常

复制与移动

java
// 复制
Files.copy(Path.of("src.txt"), Path.of("dst.txt"));
Files.copy(Path.of("src.txt"), Path.of("dst.txt"),
    StandardCopyOption.REPLACE_EXISTING); // 覆盖

// 移动(重命名)
Files.move(Path.of("old.txt"), Path.of("new.txt"));
Files.move(Path.of("old.txt"), Path.of("new/dir/new.txt"),
    StandardCopyOption.REPLACE_EXISTING);

遍历目录

java
// walk:深度优先遍历
try (Stream<Path> stream = Files.walk(Path.of("mydir"))) {
    stream.forEach(System.out::println);
}

// list:只遍历一层
try (Stream<Path> stream = Files.list(Path.of("mydir"))) {
    stream.filter(p -> p.toString().endsWith(".txt"))
          .forEach(System.out::println);
}

// find:带条件过滤
try (Stream<Path> stream = Files.find(Path.of("mydir"),
        10,  // 最大深度
        (p, a) -> p.toString().endsWith(".txt") && a.size() > 1024)) {
    stream.forEach(System.out::println);
}

文件属性

java
Files.size(path);                   // 文件大小
Files.getLastModifiedTime(path);    // 最后修改时间
Files.setLastModifiedTime(path, time); // 设置修改时间

BasicFileAttributes attr = Files.readAttributes(path, BasicFileAttributes.class);
attr.creationTime();   // 创建时间
attr.lastModifiedTime(); // 修改时间
attr.size();            // 大小
attr.isDirectory();     // 是否目录

临时文件/目录

java
// 创建临时文件
Path tempFile = Files.createTempFile("prefix", ".tmp");
Path tempFile2 = Files.createTempFile(null, ".tmp"); // 无前缀

// 创建临时目录
Path tempDir = Files.createTempDirectory("mytempdir");

// 使用完自动删除
tempFile.toFile().deleteOnExit();

File vs Path/Files

对比FilePath / Files
JDK 版本JDK 1.0JDK 7+
API分散在多个方法静态工具类
路径表示File 对象Path 接口
功能更丰富
推荐不推荐推荐

选型建议

┌─────────────────────────────────────────────────────────────────┐
│  新代码用 Path / Files,旧代码慢慢迁移                            │
│                                                                 │
│  Files 是工具类,Path 是路径表示                                  │
│  File 是历史遗留,但它还没消失                                     │
└─────────────────────────────────────────────────────────────────┘

基于 VitePress 构建