关闭输入流的正确顺序是什么?

时间:2017-01-06 01:11:09

标签: java

我正在研究一个关于使用输入流读取文件的Java代码示例。我观察到有3个输入流按fisbisdis(键入FileInputStreamBufferedInputStream和{{1}的顺序初始化相应地),依赖fis< - (依赖) - bis< - (依赖) - dis。我还观察到它们以相同的顺序关闭:DataInputStreamfis,然后是bis

我的问题是:不应该以REVERSE顺序关闭它们吗?即最近初始化的应该先关闭?

Here是代码示例。我也贴在这里:

dis

5 个答案:

答案 0 :(得分:2)

你只需要关闭外部对象(DataInputStream)。它将关闭它所依赖的所有对象。

答案 1 :(得分:2)

我会建议他们打开顺序的反面(所以disbis然后fis),但这不是必需的(只是样式)或更好但是 - try-with-resources喜欢

File file = new File("C:\\testing.txt");
try (FileInputStream fis = new FileInputStream(file);
        BufferedInputStream bis = new BufferedInputStream(fis);
        DataInputStream dis = new DataInputStream(bis)) {
    while (dis.available() != 0) {
        System.out.println(dis.readLine());
    }
} catch (IOException e) {
    e.printStackTrace();
}

答案 2 :(得分:2)

您可以使用try-with-resources而不用担心结算顺序

    public class BufferedInputStreamExample {

    public static void main(String[] args) {

        File file = new File("C:\\testing.txt");

        try(FileInputStream fis = new FileInputStream(file);
            BufferedInputStream bis = new BufferedInputStream(fis);
            DataInputStream dis = new DataInputStream(bis)) {

            while (dis.available() != 0) {
                System.out.println(dis.readLine());
            }

        } catch (IOException e) {
            e.printStackTrace();
        } 
    }
}

答案 3 :(得分:2)

正常的做法是只关闭最外面的流。 DataInputStreamBufferedInputStream都是FilterInputStreamwhose close method specifies的类型,它调用底层流的close方法。因此,您不需要显式关闭其他人,甚至不需要在变量中维护对它们的引用。例如,可以将dis初始化为:

dis = new DataInputStream(
    new BufferedInputStream(
    new FileInputStream(file)));

在实践中,假设根据规范正确实现了类,无论是以任何顺序还是以任何次数关闭任何1个,任何2个或全部3个流都无关紧要,因为:< / p>

  1. 如上所述,关闭外部流将关闭内部流。
  2. 无害地关闭已经关闭的流无效。 (InputStreamOutputStream实现Closeable接口,whose close method states&#34;如果流已经关闭,则调用此方法无效。&#34;)< / LI>
  3. 只有FileInputStream实际需要才能关闭,因为它是唯一一个保持打开真实文件系统资源的流,因此是唯一一个具有可见副作用的流,如果保持打开状态(例如,您无法删除该文件)。 BufferedInputStreamDataInputStream是普通对象,可以以普通方式进行垃圾收集,无论是否关闭。如果您忘记了垃圾收集,那么FileInputStream也将被关闭,但是尽快做到这一点是谨慎的,因为 垃圾时无法保证收集发生。
  4. 所以你发布的例子是过度设计的,但并不危险。

    在现代Java(7+)中,确保关闭示例中所有内容而不是使用finally块的更优雅的方法是使用try-with-resources语句,它可以让你宣布流,打开它们,并保证关闭,一气呵成:

    try (DataInputStream dis = new DataInputStream(
            new BufferedInputStream(
            new FileInputStream(file)))) {
        while (dis.available() != 0) {
            System.out.println(dis.readLine());
        }
    } catch (IOException e) {
        e.printStackTrace();
    }
    

答案 4 :(得分:1)

虽然文档不是100%明确,但看起来关闭DataInputStream就足够了。

DataInputStreamBufferedInputStream都是FilterInputStream的子类,这里是close()(Java 7 SE)的文档:

  

关闭此输入流并释放与该流关联的所有系统资源。此方法只执行 .close()。

此处in是包裹的流。

假设两个类都没有覆盖超类的行为,关闭DataInputStream会递归关闭所有包装的流。