Java IO 异常处理与 Properties 使用详解
本文深入解析Java IO流在开发中的异常处理机制,对比不同JDK版本的语法差异,避免手动关闭资源引发的隐患。同时结合Properties持久化属性集类,演示如何通过键值对结构读取外部配置文件,提供从安全写入到配置管理的完整实战方案。
JDK 7之前:传统 try-catch-finally 模式
在实际项目研发中,直接将异常抛出给上层并不总是最佳选择,通常需要进行捕获处理以防止程序崩溃。传统的做法是使用 try-catch-finally 代码块。核心逻辑是:在 finally 块中判断资源是否为空并执行关闭操作,确保无论发生何种情况都能释放系统资源。
操作步骤:
- 定义变量范围:
FileWriter实例需在try外部声明,以便finally块访问。 - 尝试初始化与写入:在
try中创建流对象并执行写操作。 - 捕获异常:在
catch (IOException e)中记录堆栈信息。 - 安全关闭:在
finally再次包装一次try-catch来判断并关闭流(防止关闭时再次抛出异常导致掩盖原异常)。
public class HandleException1 {
public static void main(String[] args) {
// 1. 声明变量,作用域需包含 finally
FileWriter fw = null;
try {
// 2. 创建流并写出数据
fw = new FileWriter("fw.txt");
fw.write("三分归元气");
} catch (IOException e) {
// 3. 捕获并处理读写过程中的异常
e.printStackTrace();
} finally {
// 4. 确保资源释放
if (fw != null) {
try {
fw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}JDK 7 的改进:try-with-resources 语句
JDK 7 引入了自动资源管理机制(Try-With-Resources)。实现了 AutoCloseable 接口的对象(如各种 Stream)可以直接在 try() 括号内声明。优势:JVM 会自动调用这些对象的 close() 方法,无需编写繁琐的 finally 块,代码更简洁且不易遗漏关闭。
第1步:在 try 括号中声明流
将需要自动关闭的资源对象实例化放在 try( ... ) 中。若有多个资源,以分号隔开。注意,这里声明的对象具有“最终性”(effectively final)。
第2步:执行数据操作
在 try{ } 内部进行读写字节或字符的操作。
public class HandleException2 {
public static void main(String[] args) {
// JDK7:直接在try头中创建流对象
try (FileWriter fw = new FileWriter("fw.txt");) {
// 写出数据
fw.write("三分归元气");
} catch (IOException e) {
e.printStackTrace();
}
// 退出try块时,fw已自动关闭
}
}JDK 9 的进一步优化
JDK 9 进一步放宽了限制。如果资源对象已经是 final 修饰的变量,或者在 try 之前已经被赋值为非空的局部变量,那么可以直接将该变量名放入 try 括号中,而无需重新声明创建。
应用场景对比
- JDK 7/8:必须写成
try (Resource r = resource)形式,创建新引用。 - JDK 9+:允许直接传入变量名
try (resource)。这极大简化了代码冗余。
综合读取演示(支持 JDK 9+)
利用此特性,我们可以同时管理输入和输出流。注意变量类型判定,普通变量不能直接使用,需符合上述规则。
public class TryDemo {
public static void main(String[] args) throws IOException {
// 创建源和目标对象
final FileReader fr = new FileReader("in.txt"); // final 关键字修饰
FileWriter fw = new FileWriter("out.txt"); // JDK9可直接引入
// JDK9方式:直接在括号内引入变量
try (fr; fw) {
int b;
// 边读边写
while ((b = fr.read()) != -1) {
fw.write(b);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}Properties 属性集的使用
在处理配置文件时,我们常遇到大量的 key=value 格式数据。Java 提供了 java.util.Properties 类来专门处理此类场景。它继承自 Hashtable,但只接受字符串类型的 Key 和 Value。
基础内存操作
通过 setProperty 存入数据,getProperty 获取数据。适合简单的内存键值缓存。
public class ProDemo {
public static void main(String[] args) {
// 1. 实例化对象
Properties properties = new Properties();
// 2. 添加键值对 (Key/Value 必须是 String)
properties.setProperty("filename", "a.txt");
properties.setProperty("length", "209385038");
properties.setProperty("location", "D:\\a.txt");
// 3. 根据键获取值
System.out.println(properties.getProperty("filename"));
// 4. 遍历所有键
Set<String> keys = properties.stringPropertyNames();
for (String key : keys) {
System.out.println(key + " -- " + properties.getProperty(key));
}
}
}持久化加载:load() 方法
实际项目中,配置通常存在于外部文本文件中(如 .properties 文件)。此时需使用 load(InputStream inStream) 方法将外部数据读入集合。
前提条件: 外部文件格式必须符合 key=value 规范,且每行一组。
public class ProDemo2 {
public static void main(String[] args) {
try {
Properties pro = new Properties();
// 使用字节输入流关联本地文件
// 假设当前目录下存在 read.txt
pro.load(new FileInputStream("read.txt"));
Set<String> strings = pro.stringPropertyNames();
for (String key : strings) {
System.out.println(key + " -- " + pro.getProperty(key));
}
} catch (IOException e) {
e.printStackTrace();
}
}
}以上就是关于 Java IO 异常安全处理及 Properties 配置集读取的详细内容。更多关于 Java 高级特性的学习资料请关注本站其它相关文章!
免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。









