try-with-resources 优雅的关闭 I/O 流
在 Java 中,关闭 I/O 流是一项重要的任务,它有助于释放系统资源,避免内存泄漏,并确保程序的正确性和健壮性。
1. 基础的关闭方式
最基础的关闭 I/O 流的方式是使用 close()
方法。在 Java 7 及以上版本,我们可以使用 try-with-resources 语句,它会在代码块结束时自动关闭资源。
public static void base(){// 测试使用绝对路径
try (FileInputStream fis = new FileInputStream("example.txt");
InputStreamReader isr = new InputStreamReader(fis);
BufferedReader reader = new BufferedReader(isr)) {
// 读取文件内容
String line;
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
} catch (IOException e) {
e.printStackTrace();
}
}
编译后的文件如下
public static void base() {
try {
FileInputStream fis = new FileInputStream("example.txt");
Throwable var1 = null;
try {
InputStreamReader isr = new InputStreamReader(fis);
Throwable var3 = null;
try {
BufferedReader reader = new BufferedReader(isr);
Throwable var5 = null;
try {
String line;
try {
while((line = reader.readLine()) != null) {
System.out.println(line);
}
} catch (Throwable var52) {
var5 = var52;
throw var52;
}
} finally {
if (reader != null) {
if (var5 != null) {
try {
reader.close();
} catch (Throwable var51) {
var5.addSuppressed(var51);
}
} else {
reader.close();
}
}
}
} catch (Throwable var54) {
var3 = var54;
throw var54;
} finally {
if (isr != null) {
if (var3 != null) {
try {
isr.close();
} catch (Throwable var50) {
var3.addSuppressed(var50);
}
} else {
isr.close();
}
}
}
} catch (Throwable var56) {
var1 = var56;
throw var56;
} finally {
if (fis != null) {
if (var1 != null) {
try {
fis.close();
} catch (Throwable var49) {
var1.addSuppressed(var49);
}
} else {
fis.close();
}
}
}
} catch (IOException var58) {
var58.printStackTrace();
}
}
在上述demo中,FileInputStream
、InputStreamReader
、BufferedReader
都实现了 AutoCloseable
接口,因此它们可以在 try-with-resources 语句中被自动关闭。
2. 使用 try-catch-finally
在 Java 7 之前的版本,我们可以使用传统的 try-catch-finally 结构来关闭 I/O 流。在 finally 块中确保资源被关闭。
FileInputStream fis = null;
try {
fis = new FileInputStream("example.txt");
InputStreamReader isr = new InputStreamReader(fis);
BufferedReader reader = new BufferedReader(isr);
// 读取文件内容
String line;
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (fis != null) {
fis.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
上述方法无论是否发生异常,资源都会被关闭。
3. 使用 try-with-resources 处理多个流
如果有多个需要关闭的流,可以在 try-with-resources 语句中使用多个资源。
try (FileInputStream fis = new FileInputStream("input.txt");
FileOutputStream fos = new FileOutputStream("output.txt");
BufferedReader reader = new BufferedReader(new InputStreamReader(fis));
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(fos))) {
// 读取输入文件内容并写入输出文件
String line;
while ((line = reader.readLine()) != null) {
writer.write(line);
writer.newLine();
}
} catch (IOException e) {
e.printStackTrace();
}
在上述demo中,FileInputStream
、FileOutputStream
、BufferedReader
、BufferedWriter
都在 try-with-resources 语句中,确保它们在使用完毕后被自动关闭。
4. 使用 Java NIO
Java NIO(New I/O)提供了一种更为灵活的 I/O 操作方式,其中的 java.nio.file
包提供了 Files
类,可以通过 Files.newBufferedReader
和 Files.newBufferedWriter
等方法创建带有自动关闭功能的 BufferedReader
和 BufferedWriter
。
try (BufferedReader reader = Files.newBufferedReader(Paths.get("example.txt"));
BufferedWriter writer = Files.newBufferedWriter(Paths.get("output.txt"))) {
// 读取输入文件内容并写入输出文件
String line;
while ((line = reader.readLine()) != null) {
writer.write(line);
writer.newLine();
}
} catch (IOException e) {
e.printStackTrace();
}
使用 Files
类可以更加简洁地处理文件读写,并且它们也支持 try-with-resources。
5. 使用 Apache Commons IO 库
Apache Commons IO 库提供了 IOUtils
类,其中的 closeQuietly
方法可以方便地关闭流而无需手动处理异常。注意,这种方式不会抛出异常,因此适用于一些简单的场景。
FileInputStream fis = null;
try {
fis = new FileInputStream("example.txt");
// 处理文件输入流
} finally {
IOUtils.closeQuietly(fis);
}
结论
无论选择哪种方式,都应该在程序中妥善处理 I/O 流的关闭。使用 try-with-resources 语句是一种简洁且安全的方式,但要确保相关的类实现了 AutoCloseable
接口。在旧版 Java 中,传统的 try-catch-finally 结构也是一种可靠的方式。