【问题标题】:Can closing a File fail?关闭文件会失败吗?
【发布时间】:2014-02-04 22:11:32
【问题描述】:

我看到了这段代码,想知道为什么in.close() 是在finally block 中完成的。 try-with resources 的主要观点是它 closesresources 是正确的。

  File file = new File(FILE_NAME);
          FileInputStream in = null;

        try (in = new FileInputStream(file)){
            //do something
        } catch (final FileNotFoundException e) {
            log.log(Level.WARNING, "file not found, " + file.getAbsolutePath(), e);
        } catch (final IOException e) {
            log.log(Level.WARNING, "cannot access the file for reading", e);
        } finally {
            if (in != null){
                try {
                    in.close();
                } catch (final IOException e) {
                    log.log(Level.WARNING, "Attempt to close file failed.", e);
                }
            }
        }

会不会出现在Java中使用try-with-resources可以打开文件却无法关闭的情况?

【问题讨论】:

  • 没有关闭File 这样的事情,您似乎正在关闭FileInputStream
  • 是的,这就是我的意思;关闭资源对吗?

标签: java exception finally try-with-resources


【解决方案1】:

您示例中的 finally 块是多余的。 try-with-resources 语句基本上做同样的事情(但更不容易出错!)。由于它是在 try-with-resources 语句尝试关闭资源之后执行的,所以 finally 块本质上是一个 noop(在第一次失败后可能会再次尝试关闭资源成功 - 但 如果这甚至是可能的,这是一个可以忽略不计的边缘情况,而且肯定是不确定的)。

请注意,catch 块相比之下很重要。关闭资源的尝试将在激活catch 块之前进行,从而导致发生多个异常的可能性。这可以通过使用抑制的异常来解决。因此,如果使用资源失败,仍然会尝试正确关闭它(这通常也会失败)并且 catch 块将收到第一个(最可能的根本)原因,而不是关闭隐藏第一个错误时抛出的异常。

更多信息见官方documentation

【讨论】:

    【解决方案2】:

    这不是文件独有的,它通常发生在 I/O 中。

    Java API 规定 InputStream 的 close() 方法在“发生 I/O 错误”时可能会引发异常

    所以是的,它可能会发生,这种行为会产生有趣(或不那么有趣)的 try-catch-finally-try-catch 块。

    【讨论】:

      【解决方案3】:

      我会用一些可移动存储设备(例如 U 盘)做一个简单的测试:

      只需编写一个程序,用 U 盘中的文件打开 FileInputStream,然后提示“请移除存储设备”,等待 ,然后尝试 in.close()。我敢打赌会抛出一些IOException

      【讨论】:

        【解决方案4】:

        是的,这可能发生。 close() 的方法签名确实会抛出 IOException,因此优秀的程序员应该为这种可能性做好准备。

        通常,catch 块将移到方法之外,这使得处理它更容易,看起来更干净。例如:

        public static void main(String[] args)
        {
            try {
                 readFile(new File("MyFile.txt"));
            } catch (IOException e) {
                 /* handle the exception */
            }
        }
        
        private static void readFile(File file) throws IOException
        {
            FileInputStream in = null;
        
            try {
                in = new FileInputStream(file);
                /* Read the file.  THIS MIGHT FAIL! */
            } finally {
                if (in != null) /* Check this because new FileInputStream() could have failed */
                    in.close(); /* If this throws and exception, it will be handled by main() */
            }
        }
        

        【讨论】:

        • 我想你还没有理解这个问题; try-with-resources 是自动关闭的。你不需要显式关闭它
        猜你喜欢
        • 2018-09-05
        • 1970-01-01
        • 1970-01-01
        • 2013-06-07
        • 1970-01-01
        • 2021-02-04
        • 2019-03-27
        • 2016-08-20
        • 1970-01-01
        相关资源
        最近更新 更多