java 6 IO - 包裹流关闭 [英] java 6 IO - wrapped streams closing

查看:143
本文介绍了java 6 IO - 包裹流关闭的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

考虑:

public static void read(String filename) throws IOException {
    String charsetName = "UTF-8";
    InputStream file = new FileInputStream(filename); // say no problem
    InputStreamReader reader = new InputStreamReader(file, charsetName);
    BufferedReader buffer = new BufferedReader(reader);
    try {
        buffer.readLine();
    } finally {
        try {
            buffer.close();
        } catch (IOException e) {
            // report at least
            e.printStackTrace();
        }
    }
}

如果 new InputStreamReader(file,charsetName) throws UnsupportedEncodingException buffer.close(); 线永远不会被调用。替代方案是额外的冗长:

If new InputStreamReader(file, charsetName) throws UnsupportedEncodingException, the buffer.close(); line will never be called. The alternative is extra verbose :

InputStream file = new FileInputStream(filename);
try {
    InputStreamReader reader = new InputStreamReader(file);
    try {
        BufferedReader buffer = new BufferedReader(buffer);
        try {
            buffer.readLine();
        } finally {
            buffer.close(); // should catch
        }
    } finally {
        reader.close(); // should catch
    }
} finally {
    file.close(); // should catch
}

并且不必要地关闭所有流(同时 output.close(); 应该足够 - 实际上任何一个都应该足够成功 - 查看Skeet代码中的注释)。

and it needlessly closes all streams (while output.close(); should suffice - actually any of them should suffice if successful - see comments in the code by Skeet).

包装构造函数

BufferedReader buffer = new BufferedReader(
              new InputStreamReader(new FileInputStream(filename), charsetName));

基本上只是隐藏问题。

请注意,我使用@ TomHawtin-tackline 此处建议的try-finally成语 - 但更常见的方法是:

Notice I use the try-finally idiom suggested by @TomHawtin-tackline here for instance - but the more common approach :

public static void read(String filename) throws IOException {
    String charsetName = "UTF-8";
    InputStream file = null;
    InputStreamReader reader = null;
    BufferedReader buffer = null;
    try {
        file = new FileInputStream(filename);
        reader = new InputStreamReader(file, charsetName);
        buffer = new BufferedReader(reader);
        buffer.readLine();
    } finally {
        try {
            if(buffer != null) buffer.close();
        } catch (IOException e) {
            // report at least
            e.printStackTrace();
        }
        // Rinse and repeat for the rest
    }
}

同样尴尬。

你会如何处理这个案子?< br>
将:

How would you handle this case ?
Would :

public static void read(String filename) throws IOException {
    String charsetName = "UTF-8";
    InputStream file = new FileInputStream(filename);
    try {
        InputStreamReader reader = new InputStreamReader(file, charsetName);
        BufferedReader buffer = new BufferedReader(reader); // Eclipse warning
        buffer.readLine();
        // notice that if these were out put streams we SHOULD FLUSH HERE
    } finally {
        try {
            file.close();
        } catch (IOException e) {
            // report at least
            e.printStackTrace();
        }
    }
}

做什么?换句话说, 关闭最里面的流 (与通常 超过2个包裹的流时,in-java>问会是最干净的解决方案吗? 是否有最终的情况下装饰器也应该关闭()?例如,请参阅此处。请注意,Eclipse警告:

do ? In other words closing the innermost stream (contrary to what is usually asked) would be the cleanest solution when there are more than 2 wrapped streams ? Are there cases when finally the decorator should be also closed() ? See for instance points here. Notice that Eclipse warns :


资源泄漏:缓冲区永远不会关闭

Resource leak: 'buffer' is never closed

Eclipse是对的吗?

Is Eclipse right ?

这是Java 6 - Android只是Java 6我才提醒你。试图在一些实用程序类中分解IO代码,一劳永逸

推荐答案

在上一个方法中,<根据关闭流的规则,eclipse显示的code>资源泄漏警告是正确的。关闭最里面的流只关闭该流,而不是关闭该流的其他流。但关闭最外层的流是一次性操作,它将自动关闭所有底层流。
如文章始终关闭流所述:

In your last approach , Resource leak warning as shown by eclipse is correct according to the rules of closing streams. closing the innermost stream is only closing that stream but not the other streams that has wrapped up that stream. But closing the outermost stream is one time operation that will automatically close all the underlying streams. As specified in the article Always close streams :


如果将多个流链接在一起,那么关闭
是最后一个要构建的流,因此处于最高级别
抽象,将自动关闭所有底层流。所以,
只需要在一个流上调用close来关闭(并刷新,如果适用的话,刷新
)整个系列的相关流。

If multiple streams are chained together, then closing the one which was the last to be constructed, and is thus at the highest level of abstraction, will automatically close all the underlying streams. So, one only has to call close on one stream in order to close (and flush, if applicable) an entire series of related streams.

所以在我看来,以下代码是您的案例的解决方案:

So In my opinion following code is solution for your case:

public static void read(String filename) throws IOException {
    String charsetName = "UTF-8";
    InputStream file = null;
    InputStreamReader reader = null;
    BufferedReader buffer = null;
    try 
    {
        file = new FileInputStream(filename);                
        reader = new InputStream(file,charsetName);
        buffer = new BufferedReader(reader);
        buffer.readLine();
    } 
    finally 
    {
         closeQuietly(buffer,reader,file);
    }
}

编辑

正如@jtahlborn所建议的,在finally块中编写的代码包含在实用程序方法中,如下所示:

EDIT
As suggested by @jtahlborn the code written within finally block is wrapped within a utility method as follows:

public static void closeQuietly(Closeable... closeables) 
{ 
    if(closeables == null) 
    { 
        return; 
    } 
    for (Closeable c : closeables) 
    { 
        doCloseQuietly(c); 
    } 
} 
public static void doCloseQuietly(Closeable c)
{
    try
    {
        if (c != null)
        {
            c.close();
        }
    }
    catch (IOException ex)
    {
        ex.printStackTrace();
    }
}

这篇关于java 6 IO - 包裹流关闭的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆