【问题标题】:Do I have to close FileInputStream?我必须关闭 FileInputStream 吗?
【发布时间】:2011-07-02 17:36:27
【问题描述】:

我是测试自动化领域的实习生。 我正在使用 Eclipse 创建 Junit 代码并使用 Eclipse 运行。 我正在使用 FileInputStream 函数从 excel 表中检索数据。

FileInputStream fi=new FileInputStream("c:\\search.xls");
Workbook w=Workbook.getWorkbook(fi);
Sheet s=w.getSheet(0);

是否需要关闭 Inputstream 功能?如果是这样,请指导我一些编码。

【问题讨论】:

    标签: java file-io inputstream


    【解决方案1】:

    做这样的事情。

    FileInputStream fi=null;
    try{
    fi = new FileInputStream("c:\\search.xls");
    Workbook w=Workbook.getWorkbook(fi);
    Sheet s=w.getSheet(0);
    }catch(IOException ioe){
    }finally{
    if(fi != null){
    fi.close();
    }
    fi = null;//This will be hint to get finalize() called on fi so that underlying resources used will released like files opened.
    }
    

    【讨论】:

      【解决方案2】:

      我这样做是为了确保关闭excel文件输入流,这可能会有所帮助

      abstract int workWithWorkBook(Workbook workBook);
      
      protected int doWorkBook(Path excelFile) throws IOException {
          File f = excelFile.toFile();
      
          try (FileInputStream excelContent = new FileInputStream(excelFile.toFile())){
              POIFSFileSystem fileSystem = new POIFSFileSystem(excelContent);
              Workbook workBook = null;
              if (f.getName().endsWith("xls")) {
                  workBook = new HSSFWorkbook(fileSystem);
              } else if (f.getName().endsWith("xlsx")) {
                  workBook = new XSSFWorkbook(excelContent);
              }
              return workWithWorkBook(workBook);
      
          }catch (Exception e){
              e.printStackTrace();
              throw e;
          }
      }
      

      9b9ea92b-5b63-47f9-a865-fd40dd602cd5

      【讨论】:

        【解决方案3】:

        最近,当我尝试重构我的代码时,我不得不将工作簿的创建移至另一个方法,并在该方法中创建 FileInputStream。该方法创建一个 FileInputStream 并返回一个工作簿。但是 FileInputStream 在 main 方法中是不可见的;那么我将如何在主方法结束时关闭我的 FileInputStream 呢?答案是,您不必关闭 FileInputStream,而只需关闭工作簿,它会在内部关闭 FileInputStream。简而言之,说无论如何都必须关闭 FileInputStream 是不正确的。

        【讨论】:

        • 但是Workbook接口没有一个叫close的方法,如何关闭Workbook
        【解决方案4】:

        是的!完成资源后,您应该始终释放资源。 Java 有一个强大的垃圾收集机制(请注意,它与资源管理/泄漏相比是不同的。) 所以垃圾收集器无法确定您将来是否需要资源?未能释放资源可能会导致诸如拒绝服务、性能不佳等问题。

        正如已经回答的那样,但另一个省力的方法是try with resources

            try (FileInputStream fi = new FileInputStream("c:\\search.xls")) {
        
                 //do something with fi.
                 //fi.getChannel() ;
        
            } catch(IOException e) {
                // exception handling.
            } finally {
            // some statements for finally.
           }
        

        现在您不需要显式调用 fi.close() 方法。

        【讨论】:

          【解决方案5】:

          是的,如果你想释放你的系统资源,你需要close输入流。

          FileInputStream.close() 是您所需要的。

          【讨论】:

          • 在junit测试的情况下是否需要它?进程存在后不会释放资源吗?
          • 是的,进程退出后,就没有什么可利用的了。因此,操作系统将回收资源。但想法是保持测试以稳定的方式运行,而不是等待出口完成工作。这就像在问“如果我关掉我的设备怎么办?” :-) 另外,它取决于操作系统。请在doesnt-the-jvm-release-all-the-resources-that-are-not-explicitly-closed-by-the-programmer 上查看此问题以了解更多详情
          【解决方案6】:

          关闭您使用的资源总是一个好主意,但是

          如果您在资源 B 中使用资源 A,则关闭 B 而不是 A 是明智的有一个方法。

          在你的情况下,你在Workbook中使用FileInputStream,所以你最好关闭Workbook并依赖Workbok它将关闭FileInputStream

          在这种特殊情况下,实际上,Workbook will close FileInputStreamgetWorkbook() 方法的末尾,但 close Workbook 仍然是一个好主意,以便能够被垃圾收集。

          【讨论】:

            【解决方案7】:

            Basic CompSci 101 告诉我们确保关闭以 Java 或任何语言打开的资源。所以是的,你需要关闭它们。如果你不这样做,坏的juju必然会发生。

            此外,您应该学习(并愿意)使用 Javadocs。查看 FileInputStream 和 Closeable 的 Javadoc。答案就在那里。

            【讨论】:

            • 盲目地遵循既定规则而没有批评和理解为什么?部分真的很糟糕。 坏事会发生——哦,很常见?!编程不是巫术魔法,没有提及未正确释放资源的后果(文件无法移动,通常可能会引入内存泄漏,os pool of file handles might be exausted)您的答案是无用的,而且是有害的. 投反对票。
            • 噢,我用了一种语言,你说“ZOMG,他相信巫毒教”(而不是“hhhh,他没有把它拼出来,而是选择了一些白话。”相当多的其他回应没有说明后果,除非你出去否定他们,否则你只是在有偏见的高马上爬一堆肥皂盒。为什么我不拼写这些问题(以及为什么此主题中的大多数人没有)?因为它们很容易找到合适的文献,任何进行少量研究的人都可以使用。如果您认为不合适,请选择。
            【解决方案8】:

            你要么需要close(),要么结束你的程序。

            但是,如果您不关闭文件,您可能会遇到令人困惑的问题

            • 有时单独运行测试或在同一进程中运行一组测试。 (所以你可以有一个测试,它可以以一种方式工作,但不能以另一种方式工作)
            • 您不能重命名或删除打开的文件。

            最佳做法是始终关闭已完成的资源,但是我将单元测试视为脚本,并不总是必须遵循最佳做法。

            【讨论】:

            • 关闭资源的充分理由。我会将too many open files 和内存泄漏添加到该列表中,尤其是对于长期存在的进程。
            • @Elist GC 之间需要很长时间,因为它们在清理时会关闭。
            • 诚然,过程的长生命周期通常不是原因。更常见的是——递归读取文件/目录会导致too many open files。无论如何,这两种情况我自己都见过,所以无论触发因素是什么,这都是现实生活中的场景。
            【解决方案9】:
            FileInputStream fi=null;
            try {
                fi=new FileInputStream("c:\\search.xls");
                Workbook w=Workbook.getWorkbook(fi);
                Sheet s=w.getSheet(0);
            } finally {
                if (fi!=null) {
                    fi.close();
                }
            }
            

            【讨论】:

            • 只是一个小注释 - 您还需要用 try/catch 包装 close() 语句,因为 close() 声明抛出检查的 IOException。事实上,你不能像这样使用 finally。您只能尝试/最终使用运行时异常。但是对于像 IOException 和它的子类这样的检查异常,你必须有一个 try/catch 或一个 try/catch/finally ......它不会只用 try/finally 编译。
            • 取决于是否为方法声明了 IOException。如果你抓住它,你应该知道如何处理它。重要的部分是将 close() 放在 finally 块中。事实上,对此的自动处理是我非常期待在 Java 7 中看到的特性之一。
            猜你喜欢
            • 2021-04-05
            • 2010-09-18
            • 1970-01-01
            • 1970-01-01
            • 2020-02-20
            • 2012-07-06
            • 2014-09-25
            • 2018-09-27
            • 2015-06-30
            相关资源
            最近更新 更多