Java IO:异常处理

使用完流和读写器后,需要正确关闭它们。这可以通过调用 close() 方法来实现。不过这需要花点心思。请看这段代码:

// 输入流
InputStream input = new FileInputStream("C:\\Users\\Administrator\\Desktop\\input.txt");

int data = input.read();
while(data != -1) {
    // 对数据进行一些处理...
    doSomethingWithData(data);
    data = input.read();
}

input.close(); // 关闭流

这段代码乍一看没什么问题。但如果在 doSomethingWithData() 方法中出现异常会怎样呢?没错!InputStream 永远不会关闭!

为了避免这种情况,你可以将代码重写成这样:

InputStream input = null;
try {
    input = new FileInputStream("C:\\Users\\Administrator\\Desktop\\input.txt");
    int data = input.read();
    while(data != -1) {
        // 对数据进行一些处理...
        doSomethingWithData(data);
        data = input.read();
    }
} catch(IOException e) {
    // 对异常...比如记录日志,或者再次抛出等。
} finally {
    if(input != null) {
        input.close();
    }
}

请注意 InputStream 现在是如何在 finally 子句中关闭的。无论 try 块中发生了什么,finally 子句都会被执行。因此,InputStream 将始终关闭。

但是,如果 close() 抛出异常会怎样?比如说流已经关闭了?那么,要捕获这种情况,就必须把对 close() 的调用也包在 try-catch 块中,就像这样:

try {
    //...
} catch(IOException e) {
    //...
} finally {
    try{
        if(input != null) {
            input.close();
        }
    } catch(IOException e){
        // 做点什么,或者忽略
    }
}

正确处理 InputStream(或 OutputStream)迭代的代码可能会很难看,正如你所看到的,一旦你也正确处理了异常,就会很难看。这种丑陋的异常处理代码遍布整个代码,反复出现,并不是一件好事。如果有人急于求成,跳过异常处理怎么办?

此外,假设 doSomethingWithData() 首先抛出了一个异常。第一个 catch 子句将捕获该异常,然后 finally 子句将尝试关闭 InputStream。但是,如果 input.close() 方法也抛出异常,会发生什么情况?这两个异常中的哪一个应该在调用栈中向上传播?

幸运的是,有一种方法可以解决这个问题。这个办法叫做 “异常处理模板”。创建一个异常处理模板,在使用后正确关闭数据流。该模板只需编写一次,并在整个代码中重复使用。简单易用。要了解更多信息,请访问 Java 中的异常处理模板。

Java7 的 Java IO 异常处理

从 Java 7 开始,Java 包含了一种新的异常处理机制,称为 “try with resources”。这种异常处理机制特别针对在使用需要在使用后正确关闭的资源(如 InputStream、OutputStream 等)时的异常处理。

一个简单示例:

package com.hxstrive.java_io.demo01;

import java.io.FileReader;
import java.io.Reader;

/**
 * FileReader 示例
 * @author hxstrive.com
 */
public class FileReaderDemo {

    public static void main(String[] args) {
        // try with resources
        try(Reader reader = new FileReader("C:\\Users\\Administrator\\Desktop\\input.txt")) {
            int data = reader.read();
            while(data != -1){
                char dataChar = (char) data;
                System.out.print(dataChar);
                data = reader.read();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}

上述代码,当代码正常或异常退出 try-catch 后,JVM 会自动关闭 Reader 资源。

说说我的看法
全部评论(
没有评论
关于
本网站专注于 Java、数据库(MySQL、Oracle)、Linux、软件架构及大数据等多领域技术知识分享。涵盖丰富的原创与精选技术文章,助力技术传播与交流。无论是技术新手渴望入门,还是资深开发者寻求进阶,这里都能为您提供深度见解与实用经验,让复杂编码变得轻松易懂,携手共赴技术提升新高度。如有侵权,请来信告知:hxstrive@outlook.com
公众号