IO 异常处理
你有没有被 IO 异常坑过?
凌晨上线,发现文件读取失败;同事的代码在你电脑上跑不了;服务器上的日志全是乱码——这些问题往往不是逻辑错误,而是 IO 异常处理没做好。
本节汇总 IO 开发中最常见的坑,以及正确应对方式。
FileNotFoundException:文件找不到
java
// ❌ 文件不存在或路径错误,直接抛异常
new FileInputStream("not-exist.txt");
// ✅ 先检查再操作
File f = new File("data.txt");
if (f.exists() && f.isFile()) {
try (FileInputStream fis = new FileInputStream(f)) {
// 读取文件
}
}
// ✅ 或者直接 try-catch,让异常说明问题
try {
new FileInputStream("data.txt");
} catch (FileNotFoundException e) {
System.err.println("文件不存在: " + e.getMessage());
}注意:FileNotFoundException 是 IOException 的子类。
IOException:IO 操作失败
java
// ❌ IO 错误时未处理
FileInputStream fis = new FileInputStream("data.txt");
fis.read(); // 如果磁盘读取失败,程序直接崩溃
// ✅ 用 try-catch 包裹
try {
FileInputStream fis = new FileInputStream("data.txt");
fis.read();
} catch (IOException e) {
System.err.println("IO 错误: " + e.getMessage());
e.printStackTrace();
}
// ✅ 更好的做法:try-with-resources
try (FileInputStream fis = new FileInputStream("data.txt")) {
fis.read();
} // 自动关闭,自动处理异常字符编码异常:乱码
java
// ❌ 编码不一致 → 乱码
byte[] bytes = "你好".getBytes(StandardCharsets.UTF_8);
String s = new String(bytes, StandardCharsets.GBK); // 乱码!
// ✅ 编码一致 → 正常
byte[] bytes = "你好".getBytes(StandardCharsets.UTF_8);
String s = new String(bytes, StandardCharsets.UTF_8); // "你好"异常处理的最佳实践
用 try-with-resources 代替 finally
java
// ❌ 老式写法:finally 中关闭流,容易遗漏
FileInputStream fis = null;
try {
fis = new FileInputStream("data.txt");
fis.read();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (fis != null) {
try {
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
// ✅ 现代写法:try-with-resources,自动关闭
try (FileInputStream fis = new FileInputStream("data.txt")) {
fis.read();
}嵌套流只需关最外层
java
// ❌ 多此一举
try (FileInputStream fis = new FileInputStream("data.txt");
BufferedInputStream bis = new BufferedInputStream(fis)) {
bis.read();
fis.close(); // 不需要!
} // bis.close() 会自动关闭 fis
// ✅ 只需要关最外层
try (BufferedInputStream bis = new BufferedInputStream(
new FileInputStream("data.txt"))) {
bis.read();
}异常处理速查表
| 异常类型 | 常见原因 | 解决方案 |
|---|---|---|
| FileNotFoundException | 文件不存在、路径错误、权限不足 | 先检查 f.exists(),或 try-catch |
| IOException | 磁盘错误、网络中断、读写失败 | try-catch + 合理提示用户 |
| 乱码 | 编码不一致 | 始终指定 UTF-8 编码 |
| StreamCorruptedException | 数据流格式被破坏 | 检查读写顺序是否一致 |
记住这个原则:
IO 操作永远在 try-with-resources 中进行。 编码永远显式指定 UTF-8。 异常不是洪水猛兽,是程序在告诉你「出了问题」。
