【问题标题】:Closing an input stream in Android (Java)在 Android (Java) 中关闭输入流
【发布时间】:2012-12-03 04:58:48
【问题描述】:

所以。我正在尝试在 Android 上做一些网络工作。在我的异步任务中,我正在做:

InputStream streamOfDestiny = null;

try{
    // do some network stuff here...
}
finally{
    if(streamOfDestiny != null){
        streamOfDestiny.close(); // Build error here. Apparently, closing a stream can cause an IOException. Why this is the case, I do not know. But it is. And, since this is Java, I apparently need to care.
    }
}

所以现在我得到了这个 IOException 把一切都搞砸了。我可以这样做:

InputStream streamOfDestiny = null;

try{
    // do some network stuff here...
}
finally{
    if(streamOfDestiny != null){
        try{
            streamOfDestiny.close();
        }
        catch(IOException e){
            // Hey look! I'm inside a catch block, inside a finally block!
        }
    }
}

但这看起来很糟糕。 finally 块中的 try/catch 块?多么丑陋!我完全可以让它保持关闭状态,但这对我来说似乎是一种不好的做法,而且感觉不对(我开始直播,我想完成它)。我可以这样做:

IOUtils.closeQuietly(streamOfDestiny);

但现在我必须找到 org.apache.commons.io.IOUtils 并以某种方式将其包含到我的包中。太多的工作,加上我只需要一个功能的东西增加了我的包大小。跛脚。

我总是可以编写自己的 closeQuietly 版本:

public static void closeStreamQuietly(InputStream streamToClose){
    try{
        streamToClose.close();
    }
    catch (IOException e){
        // ignore it....
    }
}

但这似乎是我在重新发明轮子,这几乎总是坏消息——感觉应该有一些不错的、优雅的方式来做这件事,而我在这里完全错过了。

各位有什么想法吗?

【问题讨论】:

    标签: java android inputstream


    【解决方案1】:

    我不知道你为什么把你的 option-2(try-catch 块在 finally)或 option-4(创建一个小 util 方法)称为丑陋或额外的工作。这是正常的,也是意料之中的。

    如果您在finally 中编写任何代码,则应该进行相关的异常处理,这里就是这种情况。

    一个你已经完成的异常处理(预防性),通过检查null 否则当streamOfDestiny 为空时它可能抛出NullPointerException

    Stream关闭的异常场景需要二次异常处理,可能是Stream为not openunavailableit's not able to release the underline resources等原因或this等场景。

    【讨论】:

    • 我不知道 - 也许是我,但 finally 块表示应该始终执行的代码,而 try 块是专门处理异常的代码,导致代码不被执行。我意识到这在这种情况下并不完全适用,但我仍然不喜欢它。选项 4 并不可怕,但我只是希望框架能够在某个地方处理这个问题……再次,感觉就像重新发明轮子?我知道这篇文章的大部分内容都是主观的 - 并且可能过于风格化......但是,嘿,我只是想看看我是否在这里遗漏了什么。
    • @user1864042 这不是重新发明轮子。 finally 块旨在执行您认为即使发生某些异常也应该运行的代码。这并不意味着您可以将任何代码放在 finally 中,Java 将自行处理预期的异常。简单来说,finally 块和异常处理是两个不同的概念。不要混合它们。如果你在 finally 块中编写一些代码,相关的异常处理应该明确地完成。无论您是在块内执行此操作、编写自定义方法、使用某些框架还是声明为 throws 等,都取决于您。
    • @Yogndra - 我明白你的意思......我想这一切都归结为这样一个事实,即我仍然不明白为什么 close 应该抛出异常 - 我认为框架应该提供一种在不抛出任何东西的情况下关闭 IO 流的方法,一种实现逻辑的方法“我这里有这个 IOStream 对象。我不再希望使用它。请关闭它,让它停止正在做的任何事情,释放任何资源(连接等)它正在使用,然后让我继续我快乐的方式。
    • @user1864042:在 Oracle 网站上提出问题 :) 这是一种通用方法。异常情况下的选择可能针对不同的程序,例如如果您想重新尝试关闭它,因为它可能保持打开状态,如果您决定不继续进行,因为无法关闭流怎么办..在不同的情况下可能会有不同的要求,因此没有为此进行通用处理.如果在您的特定应用程序中,您认为它应该被静默关闭(忽略),请为此编写一个小的 util 方法。异常处理就是根据您的应用程序的需要处理这种情况。
    【解决方案2】:

    直接从网上复制 IOUtils 代码:

    http://grepcode.com/file/repo1.maven.org/maven2/commons-io/commons-io/1.4/org/apache/commons/io/IOUtils.java#IOUtils.closeQuietly%28java.io.InputStream%29

    另外,要习惯在 finally 块中处理异常。这不会是您最后一次看到它。

    【讨论】:

      【解决方案3】:

      这并不神秘。在大多数实现中close() 调用flush()(请参阅Javadoc 中的FilterOutputStream),并且flush() 可以抛出IOException,,因为它可能执行I/O。其他可能性是可以想象的。

      【讨论】:

        【解决方案4】:

        您应该对资源使用 try。

        try (InputStream streamOfDestiny = ...) {
            //Do you networking stuff
        } catch (IOException ioe) {
            //Handle the exceptions
        }
        

        【讨论】:

          猜你喜欢
          • 2012-07-01
          • 2021-03-09
          • 2015-06-18
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多