Skip to content

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

注意FileNotFoundExceptionIOException 的子类。

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。 异常不是洪水猛兽,是程序在告诉你「出了问题」。

基于 VitePress 构建