Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/361.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
关闭Java FileInputStream_Java_Exception_Stream - Fatal编程技术网

关闭Java FileInputStream

关闭Java FileInputStream,java,exception,stream,Java,Exception,Stream,好的,我一直在做以下工作(变量名已更改): 最近,我开始使用FindBugs,这表明我没有正确地关闭流。我决定看看是否有什么可以用finally{}块来完成,然后我看到,哦,是的,close()可以抛出IOException。人们应该在这里做什么?Java库抛出太多已检查的异常。类似于以下内容的操作应该可以做到这一点,这取决于您在尝试关闭流时是否抛出或吞下IOException FileInputStream fis = null; try { fis = new FileInputSt

好的,我一直在做以下工作(变量名已更改):


最近,我开始使用FindBugs,这表明我没有正确地关闭流。我决定看看是否有什么可以用finally{}块来完成,然后我看到,哦,是的,close()可以抛出IOException。人们应该在这里做什么?Java库抛出太多已检查的异常。

类似于以下内容的操作应该可以做到这一点,这取决于您在尝试关闭流时是否抛出或吞下IOException

FileInputStream fis = null;
try
{
    fis = new FileInputStream(file);

    ... process ...


}
catch (IOException e)
{
    ... blah blah blah ...
}
finally
{
    try
    {
        if (fis != null)
            fis.close();
    }
    catch (IOException e)
    {
    }
}

您还可以使用简单的静态帮助器方法:

public static void closeQuietly(InputStream s) {
   if (null == s) {
      return;
   }
   try {
      s.close();
   } catch (IOException ioe) {
      //ignore exception
   }
}

从finally块中使用它。

希望有一天我们会在Java中得到闭包,然后我们会失去很多详细信息

因此,取而代之的是一个助手方法,在javaIO中,您可以导入它,它可能需要一个“可关闭”接口和一个块。在这个helper方法中,try{closable.close()}catch(IOException ex){//blah}是一次性定义的,然后您就可以编写

 Inputstream s = ....;
 withClosable(s) {
    //your code here
 }

没有什么要补充的,除了一个非常小的风格建议自文档化代码的典型示例在本例中适用-为被忽略的
IOException
提供一个描述性变量名,您必须抓住
close()

斯奎德尔的答案是:

public static void closeQuietly(InputStream s) {
   try {
      s.close();
   } catch (IOException ignored) {
   }
}

您主要关心的是从FindBugs获得一个干净的报告,还是拥有可以工作的代码?这些不一定是同一件事。您的原始代码很好(尽管如果(fis!=null)检查时,我会去掉冗余的
,因为如果不是这样,就会抛出
OutOfMemoryException
)。FileInputStream有一个终结器方法,它将在处理过程中实际收到IOException时为您关闭流。为了避免极不可能发生的错误,不值得费心让代码更复杂

  • 你得到一个IOException,然后
  • 这种情况经常发生,以至于您开始遇到终结器积压问题
  • 编辑:如果您遇到太多IOException,以致于在终结器队列中遇到问题,那么您将面临更大的麻烦!这是关于获得透视感。

    对于Java 7及以上版本,应使用:

    try (InputStream in = new FileInputStream(file)) {
      // TODO: work
    } catch (IOException e) {
      // TODO: handle error
    }
    
    如果您被困在Java 6或更低版本上

    此模式可避免使用null

        try {
            InputStream in = new FileInputStream(file);
            try {
                // TODO: work
            } finally {
                in.close();
            }
        } catch (IOException e) {
            // TODO: error handling
        }
    


    有关如何有效处理close的更多详细信息,请阅读以下博文:。它有更多的示例代码,更深入,并且覆盖了在catch块中封装close的陷阱。

    在大多数情况下,我发现捕获IO异常比捕获IO异常更好,只需使用try finally:

    final InputStream is = ... // (assuming some construction that can't return null)
    try {
        // process is
        ...
    } finally {
        is.close();
    }
    
    除了
    FileNotFoundException
    ,您通常无法“处理”
    IOException
    。剩下要做的唯一一件事就是报告一个错误,您通常会在调用堆栈中进一步处理它,因此我发现传播异常更好

    由于
    IOException
    是一个选中的异常,因此您必须声明此代码(及其任何客户端)
    抛出IOException
    。这可能太吵了,或者您可能不想透露使用IO的实现细节。在这种情况下,可以使用异常处理程序包装整个块,该异常处理程序将
    IOException
    包装为
    RuntimeException
    或抽象异常类型


    详细信息:我知道当
    块中的
    关闭
    操作最终产生
    IOException时,上述代码会从
    try
    块中吞下任何异常。我不认为这是一个大问题:通常,来自
    try
    块的异常与导致
    close
    失败的
    IOException
    是同一个
    。如果这是一个问题,那么可能值得费心“静默”关闭。

    如果关闭失败,下面的解决方案会正确抛出异常,而不会在关闭前隐藏可能的异常

    try {
        InputStream in = new FileInputStream(file);
        try {
            // work
            in.close();
        } finally {
            Closeables.closeQuietly(in);
        }
    } catch(IOException exc) {
        // kernel panic
    }
    
    这是因为第二次调用close

    这依赖于番石榴,但如果愿意,可以编写自己的方法,如所示(另请参见)

    在一般情况下,报告close错误非常重要,因为close可能会向流写入一些最终字节,例如由于缓冲。因此,您的用户想知道它是否失败,或者您可能想采取某种行动。当然,在FileInputStream的特定情况下,这可能不是真的,我不知道(但由于前面提到的原因,我认为如果发生关闭错误,最好报告关闭错误)

    由于嵌入式try块的结构,上面的代码有点难以理解。有两种方法可能会更清楚,一种是抛出IOException,另一种是捕获IOException。至少我会选择这样

    private void work() throws IOException {
        InputStream in = new FileInputStream(file);
        try {
            // work
            in.close();
        } finally {
            Closeables.closeQuietly(in);
        }
    }
    
    public void workAndDealWithException() {
        try {
            work();
        } catch(IOException exc) {
            // kernel panic
        }
    }
    
    基于(由McDowell引用)。

    您可以使用添加的JDK7功能。它的创建正是为了处理这类事情

    static String readFirstLineFromFile(String path) throws IOException {
      try (BufferedReader br = new BufferedReader(new FileReader(path))) {
        return br.readLine();
      }
    }
    
    文件说:

    try with resources语句确保关闭每个资源 在陈述的结尾


    在这里依赖终结器是一个非常糟糕的举动。只有在对流对象进行垃圾收集时,才会调用终结器,并且您很可能在垃圾收集之前很久就用完了文件句柄。永远不要依赖终结器实现功能。我再怎么强调也不为过。根本无法保证终结器是否会运行。我知道依赖终结器的危险。我的观点很简单,获取IOExceptions不是一个正常的流程,对于这种不寻常的情况,可能不值得在关闭文件描述符时挂起太多的电话。您上次在一个文件输入流中看到多个IOVORATION是什么时候?
    static String readFirstLineFromFile(String path) throws IOException {
      try (BufferedReader br = new BufferedReader(new FileReader(path))) {
        return br.readLine();
      }
    }