Java,关闭内联流

时间:2014-09-17 13:46:17

标签: java stream

编辑:忘了提我正在使用java 6

我想知道如何关闭java中的资源。

看,我总是像这样初始化流:

ZipInputStream zin = null;

try {
    zin = new ZipInputStream(new BufferedInputStream(new FileInputStream(file)));
    // Work with the entries...
    // Exception handling
} finally {
    if (zin!=null) { try {zin.close();} catch (IOException ignored) {} }
}

但是,如果在new ZipInputStream(...)中抛出异常,那么new BufferedInputStream中打开的流量会不会泄漏FileInputStream吗?

如果是,那么确保资源关闭的最有效方法是什么?,我是否必须保留对每个new ...Stream的引用并在finally块中关闭它们?或者最终的流(在这种情况下是ZipInputStream)是否应该以其他方式实例化?。

欢迎任何评论。

4 个答案:

答案 0 :(得分:3)

你可以做到

try (InputStream s1 = new FileInputStream("file");
     InputStream s2 = new BufferedInputStream(s1);
     ZipInputStream zin = new ZipInputStream(s2)) {
    // ...
} catch (IOException e) {
    // ...
}

进一步阅读:The Java™ Tutorials: The try-with-resources Statement

答案 1 :(得分:1)

可以这样做:

BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file));
try {
    ZipInputStream zin = new ZipInputStream(bis);
    try {
        zin = ;
        // Work with the entries...
        // Exception handling
    } finally {
        zin.close();
    }
} finally {
    bis.close();
}

您可以在任意位置添加错误缓存。

答案 2 :(得分:0)

是的,新的ZipInputStream()或新的BufferedInputStream()中的异常会泄漏封闭的Streams,除非您在异常处理中进行级联检查:

FileInputStream fin = null;
BufferedInputStream bin = null;
ZipInputStream zin = null;

try {
    fin = new FileInputStream(file);
    bin = new BufferedInputStream(fin)
    zin = new ZipInputStream(bin);
    // Work with the entries...
    // Exception handling
} finally {
  try {
    if (zin!=null) {
       zin.close();
     } else if (bin != null) {
       bin.close();
     } else if (fin != null) {
       fin.close();
     }
  } catch (Exception e) {
    // ignore
  }
}

但是,由于BufferedInputStream和ZipInputStream仅仅是FileInputStream的包装器,因此Exception的概率相当低。如果有的话,一旦开始阅读和处理数据,最有可能发生异常。在这种情况下,创建了zin,并且zin.close()就足够了。

答案 3 :(得分:0)

首先让我们来看看你有什么以及它可能出现什么问题:

try {
    zin = new ZipInputStream(new BufferedInputStream(new FileInputStream(file)));
    // Work with the entries...
    // Exception handling
} finally {
    if (zin!=null) { try {zin.close();} catch (IOException ignored) {} }
}

a。)抛出新的FileInputStream(),不会分配zin。在这种情况下无需关闭。好吧。
b。)新的BufferedInputStream()抛出(可能是OutOfMemoryError),未分配zin。泄露FileInputStream()。坏。
c。)抛出新的ZipInputStream(),不会分配zin。要关闭BufferedInputStream和FileInputStream。关闭任何一个就足够了。坏。

每当你一个流包装到另一个流中时,你就有可能泄漏你正在包装的流。你需要引用它并在某处关闭它。

一种可行的方法是首先声明一个InputStream可变地保存最后一个create 流(或者换句话说,最外面的嵌套流):

InputStream input = null;
try {
    input = new FileInputStream(...);
    input = new BufferedInputStream(input);
    input = new ZipInputStream(input);
    ZipInputStream zin = (ZipInputStream) input;
    // work here
} finally {
     if (input != null)
         try { input.close(); } catch (IOException ignored) {}
}

这是有效的,因为如果任何new *Stream()抛出,变量input仍然跟踪之前创建的流。从input到ZipInputStream的丑陋演员是必要的,因为您必须声明input是与所有创建的流兼容的类型赋值。