393. Java 文件操作基础 - 异常捕获与处理
各位同学,写文件读文件时,异常(Exception)几乎是家常便饭。比如:
- 预期存在的文件突然不见了 🗑️
- 程序对某个目录没有访问权限 🚫
- 底层文件系统不支持某个功能 ⚠️
所以,写文件 I/O 代码时,处理异常绝对不能省略。
1️⃣ IOException —— 文件 I/O 的“通用异常”
几乎所有访问文件系统的方法都可能抛出 IOException。 👉 我们的代码必须对它进行处理,否则会直接报错并中断程序。
2️⃣ try-with-resources —— 最推荐的写法 ✅
从 Java SE 7 开始,我们有了 try-with-resources 语法。 它的好处是:
- 不用自己写 finally,编译器会自动帮你关闭资源(比如文件流、通道等)。
- 让代码更简洁,不容易忘记关资源。
示例 👇
Charset charset = Charset.forName("US-ASCII");
String s = "Hello Java I/O!";
Path file = Paths.get("output.txt");
try (BufferedWriter writer = Files.newBufferedWriter(file, charset)) {
writer.write(s, 0, s.length());
} catch (IOException x) {
System.err.format("IOException: %s%n", x);
}
🔎 解读:
try (BufferedWriter writer = ...)表示创建了一个自动关闭的资源。- 不管代码是正常结束,还是
catch了异常,writer.close()都会被自动调用。 - 这是最推荐的写法,简洁 + 安全。
3️⃣ 传统的 try-catch-finally 写法 ⚠️(不推荐)
在 Java 7 之前,我们只能这样写:
Charset charset = Charset.forName("US-ASCII");
String s = "Hello Old Java!";
BufferedWriter writer = null;
try {
writer = Files.newBufferedWriter(Paths.get("output.txt"), charset);
writer.write(s, 0, s.length());
} catch (IOException x) {
System.err.format("IOException: %s%n", x);
} finally {
try {
if (writer != null) writer.close();
} catch (IOException x) {
System.err.format("IOException when closing: %s%n", x);
}
}
🔎 解读:
- 必须在 finally 里 手动关闭资源。
- 如果忘记关,程序可能会占用文件不释放,导致崩溃。
- 看起来更麻烦,现在基本只用于老项目。
4️⃣ FileSystemException —— 更详细的异常信息
除了通用的 IOException,Java 还提供了 FileSystemException 及其子类,用来描述更具体的错误原因。
👉 它提供了一些很有用的方法:
getFile()—— 出错的文件getReason()—— 出错的原因getOtherFile()—— 另一个涉及的文件(比如重命名时的目标文件)
示例 👇
try {
Files.newBufferedReader(Paths.get("not_exists.txt"));
} catch (NoSuchFileException x) {
System.err.format("文件不存在: %s%n", x.getFile());
}
输出可能是:
文件不存在: not_exists.txt
5️⃣ 实战建议 🚀
- 写 任何文件 I/O 代码时,一定要捕获并处理异常。
- 优先用 try-with-resources,简洁又安全。
- 如果需要更具体的信息,比如哪个文件不存在,可以使用 FileSystemException 子类。
✅ 总结一句: 文件操作中,异常处理和资源关闭是必修课,谁忘了谁吃亏!