文章目录
- [417. 现代 Java IO 最佳实践 - 高效遍历、ZIP 处理与临时文件管理](#417. 现代 Java IO 最佳实践 - 高效遍历、ZIP 处理与临时文件管理)
- [📂 Java Files API 常见操作(现代写法)](#📂 Java Files API 常见操作(现代写法))
-
- [1. 🔎 遍历目录和子目录](#1. 🔎 遍历目录和子目录)
-
- [1.1 遍历当前目录 (`Files.list`)](#1.1 遍历当前目录 (
Files.list)) - [1.2 遍历子目录 (`Files.walk`)](#1.2 遍历子目录 (
Files.walk)) - [1.3 限制遍历深度](#1.3 限制遍历深度)
- [1.4 高级控制:`Files.walkFileTree`](#1.4 高级控制:
Files.walkFileTree) - [1.5 其他方法对比](#1.5 其他方法对比)
- [1.1 遍历当前目录 (`Files.list`)](#1.1 遍历当前目录 (
- [2. 📦 处理 ZIP 文件](#2. 📦 处理 ZIP 文件)
- [3. 📝 创建临时文件和目录](#3. 📝 创建临时文件和目录)
- [4. 🎓 总结 & 最佳实践](#4. 🎓 总结 & 最佳实践)
- [🔥 课堂练习建议](#🔥 课堂练习建议)
417. 现代 Java IO 最佳实践 - 高效遍历、ZIP 处理与临时文件管理
📂 Java Files API 常见操作(现代写法)
java.nio.file.Files 类提供了一套功能非常全面的文件操作方法,包括:
- 创建、复制、移动、删除 文件和目录
- 遍历目录和子目录
- 处理 ZIP 压缩文件
- 创建临时文件和目录
这些方法大大简化了文件 I/O 操作,避免了老旧的 java.io.File 的繁琐用法。
1. 🔎 遍历目录和子目录
1.1 遍历当前目录 (Files.list)
如果只需要访问某个目录下的 直接子项(文件、子目录、符号链接),可以用:
java
try (Stream<Path> entries = Files.list(Path.of("/tmp"))) {
entries.forEach(System.out::println);
}
👉 注意:
Files.list不会递归进入子目录。- 需要
try-with-resources来确保Stream被关闭,否则会导致资源泄漏。
1.2 遍历子目录 (Files.walk)
如果需要递归访问整个目录树,使用 Files.walk:
java
try (Stream<Path> entries = Files.walk(Path.of("/tmp"))) {
List<Path> htmlFiles = entries
.filter(p -> p.toString().endsWith(".html"))
.toList();
htmlFiles.forEach(System.out::println);
}
✅ 特点:
- 默认会递归遍历所有子目录。
- 可以结合
filter/map等 Stream 操作做筛选。
1.3 限制遍历深度
如果只想访问目录下 有限层级,可以传递深度参数:
java
try (Stream<Path> entries = Files.walk(Path.of("/tmp"), 2)) {
entries.forEach(System.out::println);
}
1.4 高级控制:Files.walkFileTree
在某些场景下(例如 删除整个目录树 ),我们可能需要更精细的控制。
这时可以使用 FileVisitor:
java
Files.walkFileTree(Path.of("/tmp/mydir"), new SimpleFileVisitor<>() {
@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
Files.delete(file); // 删除文件
return FileVisitResult.CONTINUE;
}
@Override
public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException {
Files.delete(dir); // 删除空目录
return FileVisitResult.CONTINUE;
}
});
👉 这比 Files.walk 更复杂,但更灵活。
1.5 其他方法对比
Files.find:类似walk,但允许直接传递(Path, BasicFileAttributes)过滤器 → 更高效。Files.newDirectoryStream:可用于for-each遍历,但几乎没有优势。File.list()/File.listFiles():过时,建议避免使用。
2. 📦 处理 ZIP 文件
从 Java 8 开始,可以把 ZIP 文件当作一个 虚拟文件系统 来操作,非常优雅。
java
Path zipPath = Path.of("example.zip");
try (FileSystem fs = FileSystems.newFileSystem(zipPath)) {
try (Stream<Path> entries = Files.walk(fs.getPath("/"))) {
List<Path> filesInZip = entries
.filter(Files::isRegularFile)
.toList();
filesInZip.forEach(System.out::println);
}
// 读取文件内容
String content = Files.readString(fs.getPath("/LICENSE"));
System.out.println(content);
}
👉 好处:
- 可以直接用
Files.readString / writeString等方法操作 ZIP 内的文件。 - 不需要手动使用
ZipInputStream / ZipOutputStream。
3. 📝 创建临时文件和目录
在开发工具、测试、外部进程交互时,常常需要 临时文件或目录。
java
Path tempFile = Files.createTempFile("myapp", ".txt");
Path tempDir = Files.createTempDirectory("myapp");
System.out.println("临时文件:" + tempFile);
System.out.println("临时目录:" + tempDir);
- 在 Linux 默认位置
/tmp,在 Windows 默认是用户临时目录。 - 系统重启后一般会清理,但最好在程序结束时手动删除。
4. 🎓 总结 & 最佳实践
✅ 推荐做法
- 用
Files.list或Files.walk遍历目录 - 用 ZIP 文件系统处理压缩包
- 用
Files.createTempFile / createTempDirectory管理临时文件
⚠️ 避免做法
- 不要再用
java.io.File的list()或listFiles(),已经过时。 - 不要手动写
while (in.read())这种循环,大多数场景下readAllBytes()或transferTo()更简洁。
🔥 课堂练习建议
- 遍历一个目录,找出所有
.java文件并打印路径。 - 读取一个 ZIP 文件,列出里面的所有
.txt文件。 - 创建一个临时目录,把几行文本写到临时文件里,然后打印内容。