java:我需要关闭所有流吗?

时间:2011-05-17 23:06:57

标签: java memory-leaks inputstream

我有一个从文件中读取文本的方法;可能需要解压缩,具体取决于输入参数:

public static String readText(File inFile, boolean compressed) {
    InputStream in = null;
    InputStreamReader isr = null;
    StringBuilder sb = new StringBuilder();//constant resizing is costly, so set the STRING_SIZE
    try {
        in = new FileInputStream(inFile);
        if (compressed) {
            in = new GZIPInputStream(in);
        }
        isr = new InputStreamReader(in);
        int length = 0;
        char[] cbuf = new char[8 * 1024];
        while ((length = isr.read(cbuf)) != -1) {
            sb.append(cbuf, 0, length);
        }
    } catch (Exception e) {
        e.printStackTrace();
    } finally {
        try {
            in.close();
        } catch (Exception e1) {
            e1.printStackTrace();
        }
    }
    return sb.toString();
}

有人建议我像这样使用InputStream,这样写起来就容易了,所以最后我只需关闭一件事。我仍然有点担心这可能会导致内存泄漏。所以我的问题是:有谁知道上面的代码是否正常?或者我是否必须回到十几个流并在finally块中逐个关闭它们?

非常感谢。

3 个答案:

答案 0 :(得分:3)

是的,关闭最外面的流/阅读器就足够了。

但是,您的代码还有另一个潜在的错误:new InputStreamReader(in)将使用平台默认编码,这取决于操作系统区域/语言设置。您应该指定文本文件的编码并在构造函数中显式使用它。

答案 1 :(得分:2)

这里有一点要补充:在调用'in.close()'之前看看'in'是否为null,因为如果没有第一个赋值成功就会发生异常。

此外,仅捕获可能的异常(例如IOException)是一种很好的形式。这样,如果您添加更多代码并且IDE告诉您未处理新的异常类型,您可以添加适当的特定代码而不是从未听过它,因为最初用于IOException的catch(异常)也是(错误处理? )其他所有类型。

答案 2 :(得分:0)

这是干净的Java 7方式,适用于任何实现AutoCloseable / Closeable的方法:

try (InputStream in = compressed ?
                        new GZIPInputStream(new FileInputStream(inFile))
                      : new FileInputStream(inFile);
     InputStreamReader isr = new InputStreamReader(in))
{
    int length = 0;
    char[] cbuf = new char[8 * 1024];
    while ((length = isr.read(cbuf)) != -1) {
        sb.append(cbuf, 0, length);
    }
}
catch (Exception e) {
    e.printStackTrace();
}

如果您想知道在关闭资源时发生异常会发生什么,请阅读同时添加的getSuppressedExceptions()。