
Java中IOException必须捕获或声明,不能忽略
Java的IO流操作(如FileInputStream、BufferedReader)抛出的是受检异常(checked exception),编译器强制你处理它。不处理会直接编译失败,不是运行时才暴露的问题。
常见错误现象:Unhandled exception type IOException;有人用空catch块“吞掉”异常,结果读文件失败却静默返回null或默认值,后续NPE或逻辑错乱。
- 要么用
try-catch捕获并做有意义的处理(比如记录日志、提示用户、提供默认数据) - 要么在方法签名加
throws IOException,把责任上抛——但注意,上层也得接住,不能一路甩到main还不管 - 别用
catch (Exception e)笼统捕获,会掩盖NullPointerException等真正该修复的bug
用try-with-resources自动关闭流,避免资源泄漏
手动调用close()容易遗漏:比如read()中途抛异常,finally里没判空就调close()可能NPE;或者忘了写finally,流一直占着文件句柄或socket连接。
使用场景:所有实现了AutoCloseable的IO类(FileInputStream、OutputStreamWriter、Scanner等)都适用。
立即学习“Java免费学习笔记(深入)”;
- 语法是
try (ResourceType resource = new ResourceType()) { ... },括号内声明的资源会在try结束时自动close() - 多个资源用分号隔开:
try (var in = new FileInputStream(...); var out = new FileOutputStream(...)) - 即使try块中抛出异常,
close()仍会执行;如果close()本身也抛异常,它会被抑制(suppressed),可通过getSuppressed()获取,不影响主异常传播
try (var reader = new BufferedReader(new FileReader("data.txt"))) {
String line = reader.readLine();
System.out.println(line);
} // reader.close() 自动在此调用
Files工具类比传统File更安全、更简洁
老式File类的delete()、mkdirs()等方法失败只返回false,不告诉你为什么;路径拼接靠字符串+,容易出../../绕过校验或Windows/Linux路径分隔符问题。
java.nio.file.Files是Java 7引入的现代替代方案,所有操作都抛IOException或子类(如NoSuchFileException),错误信息明确。
- 创建目录用
Files.createDirectories(path),失败直接抛异常,不用自己检查返回值 - 读取整个文件用
Files.readString(path)(Java 11+)或Files.readAllBytes(path),一行代码搞定,不用手动开流、缓冲、关流 - 复制/移动用
Files.copy(source, target, StandardCopyOption.REPLACE_EXISTING),选项语义清晰,不会意外覆盖或静默失败 - 路径拼接统一用
Paths.get("a", "b", "c.txt"),自动适配系统分隔符
字符编码不指定就踩坑,尤其跨平台或含中文时
很多IO操作默认用平台编码(Windows是GBK,Linux/macOS通常是UTF-8),同一段代码在不同机器上读写中文文件,可能乱码或抛MalformedInputException。
典型错误:用new FileReader("text.txt")或new FileWriter("out.txt")——它们不接受编码参数,只能用平台默认编码。
- 读文本优先用
Files.newBufferedReader(path, StandardCharsets.UTF_8) - 写文本用
Files.newBufferedWriter(path, StandardCharsets.UTF_8) - 如果必须用
InputStreamReader,务必显式传入StandardCharsets.UTF_8,别依赖new InputStreamReader(in)的无参构造 - 网络传输或配置文件中,UTF-8是事实标准,除非明确要求兼容旧系统,否则不要用GBK/ISO-8859-1
最常被忽略的是:Files.readString()和Files.write()这些便捷方法,默认就是UTF-8,但FileReader/FileWriter不是。混用这两套API,一个读一个写,中文就丢一半。









