繁体   English   中英

close是否会抛出IOException?

[英]Does close ever throw an IOException?

在这里提供了一些答案并阅读了一些注释后,似乎实际上IOException永远不会在文件I / O上关闭。

是否有任何情况下,在Stream / Reader / Writer上调用close实际上会抛出IOException?

如果实际抛出异常,应如何处理?

我发现了两个案例:

  • 当要刷新的缓冲区中仍有数据时丢失网络连接。
  • 当缓冲区中仍有数据要刷新时,让文件系统填满(或达到文件大小的用户限制)。

这两个示例都依赖于缓冲区中仍有数据时发生的事情。 在文件关闭之前关闭刷新缓冲区,因此如果将数据写入文件时出错,则会抛出IOException。

如果执行以下代码,将其传递给要在网络驱动器上创建的文件的名称,然后在按Enter键之前拔下网络电缆,则会导致程序在关闭时抛出IOException。

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;

public class Test
{
    public static void main(final String[] argv)
    {
        final File file;

        file = new File(argv[0]);
        process(file);
    }

    private static void process(final File file)
    {
        Writer writer;

        writer = null;

        try
        {
            writer = new FileWriter(file);
            writer.write('a');
        }
        catch(final IOException ex)
        {
            System.err.println("error opening file: " + file.getAbsolutePath());
        }
        finally
        {
            if(writer != null)
            {
                try
                {
                    try
                    {
                        System.out.println("Please press enter");
                        System.in.read();
                    }
                    catch(IOException ex)
                    {
                        System.err.println("error reading from the keyboard");
                    }

                    writer.close();
                }
                catch(final IOException ex)
                {
                    System.err.println("See it can be thrown!");
                }
            }
        }
    }
}

从Java 7开始,您可以使用try-with-resources来摆脱这种混乱(删除了close()操作的显式异常生成代码):

private static void process(final File file) {
    try (final Writer writer = new FileWriter(file)) {
        writer.write('a');
    } catch (final IOException e) {
        // handle exception
    }
}

这将自动神奇地处理close()的异常,并在内部执行显式null检查。

当它确实发生时,它应该像任何其他IOException一样处理,而不是像你经常看到推荐那样默默地被忽略。 我猜这个假设是,既然你已经完成了使用流,那么它是否被正确清理并不重要。

但是,正确清理很重要。 如果close()操作确实引发异常,则可能是它涉及刷新某些输出,提交某些事务(在数据库连接的情况下,您认为是只读的)等等 - 绝对不应该忽略。 而且,由于这种情况很少见,因此您不会通过中止操作来显着降低应用程序的可靠性。

对于文件,您可能看不到在close()上经常抛出的IOException,但您肯定会看到非文件I / O,如关闭网络套接字。

下面是一个Java错误示例 ,其中关闭UDP套接字最终导致抛出IOException。

它特别是FileInputStream.close ,它不会抛出,即使你的硬盘驱动器着火了。 据推测,套接字输入是一样的。 对于输出流,您也可能正在刷新。 直到最近[查看时间戳] BufferedOutputStream用于在flush抛出时无法关闭底层流。

(@MaartenBodewes希望我指出API文档没有指定不抛出的FileInputStream.close 。在帖子发布时,通常会忽略提及这与Sun JDK(现在称为Oracle JDK)相关的条款看起来,Android曾经使用的一个名为Apache Harmony的模糊的前重新实现可能有不同的行为。可能还有其他实现,或OpenJDK的版本,也可能抛出。)

检查调用close时会发生什么,异常隐藏如何影响你以及你可以做些什么: 博客文章

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM