close 是否会抛出 IOException?

发布于 2024-07-13 19:13:15 字数 162 浏览 8 评论 0原文

在此处提供了一些答案并阅读了一些评论之后,似乎在实践中,文件 I/O 的关闭时永远不会引发 IOException。

是否存在对 Stream/Reader/Writer 调用 close 实际上抛出 IOException 的情况?

如果确实抛出了异常,应该如何处理?

After providing some answers here, and reading some comments, it would seem that, in practice IOException is never thrown on close for file I/O.

Are there any cases in which calling close on a Stream/Reader/Writer actually throws an IOException?

If an exception is actually thrown, how should it be dealt with?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

ら栖息 2024-07-20 19:13:15

我发现了两种情况:

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

这两个示例都依赖于缓冲区中仍有数据时发生的事情。 Close 在文件关闭之前刷新缓冲区,因此如果将数据写入文件时出错,则会抛出 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 检查。

I have found two cases:

  • Losing the network connection when there is still data in the buffer to be flushed.
  • Having the file system fill up (or reaching your user limit for file size) when there is still data in the buffer to be flushed.

Both of those examples depend on something happening while there is still data in the buffer. Close flushes the buffer before the file is closes, so if there is an error writing the data to the file it throws an IOException.

If you execute the following code passing it the name of a file to create on a network drive, and then before you press the enter key unplug your network cable, it will cause the program to throw an IOException in close.

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!");
                }
            }
        }
    }
}

Since Java 7 you can use try-with-resources to get out of this mess (removed explicit exception generation code for the close() operation):

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

this will auto-magically handle the exceptions in close() and it performs an explicit null check internally.

冬天旳寂寞 2024-07-20 19:13:15

当它确实发生时,应该像任何其他 IOException 一样处理它,而不是像您经常看到的建议那样默默地忽略。 我猜想,既然您已经使用完流,那么它是否被正确清理并不重要。

然而,正确的清洁很重要。 如果 close() 操作确实引发了异常,则很可能涉及刷新某些输出、提交某些事务(在您认为是只读的数据库连接的情况下)等 - 当然不应该被忽视。 而且,由于这种情况很少见,因此中止操作不会显着损害应用程序的可靠性。

When it does happen, it should be handled like any other IOException, not silently ignored like you see recommended so often. The assumption is, I guess, that since you're done using the stream, it doesn't matter if it was cleaned up properly.

However, cleaning up properly is important. If a close() operation does raise an exception, its likely that it involved flushing some output, committing some transaction (in the case of a database connection you thought was read-only), etc.—definitely not something that should be ignored. And, since it is rare, you're not compromising the reliability of your application significantly by aborting the operation.

凉城已无爱 2024-07-20 19:13:15

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

这是一个 Java 错误示例,其中关闭 UDP 套接字最终导致 IOException被扔掉。

For files, you may not see IOException thrown often on close(), but you'll definitely see it for non-File I/O like closing sockets to the network.

Here's an example of a Java bug where closing a UDP socket eventually caused an IOException to be thrown.

心奴独伤 2024-07-20 19:13:15

它特别是 FileInputStream.close ,即使您的硬盘着火,也不会抛出异常。 想必套接字输入也是如此。 对于输出流,您也可能会刷新。 直到最近[参见时间戳],如果 flush 抛出异常,BufferedOutputStream 过去常常无法关闭底层流。

(@MaartenBodewes 希望我指出 API 文档中没有指定 FileInputStream.close not throwing。在发帖时,通常会忽略提到这与 Sun 相关的条款。 JDK(现在称为 Oracle JDK 和 OpenJDK),Android 过去使用的一种名为 Apache Harmony 的不起眼的重新实现可能具有不同的行为,其他实现或 OpenJDK 版本也可能会抛出异常。

It's specifically FileInputStream.close which does not throw, even if your hard drive is on fire. Presumably it is the same for socket input. For output streams you may also be flushing. Until relatively recently [see timestamps] BufferedOutputStream used to fail to close the underlying stream if flush threw.

(@MaartenBodewes would like me to point out that FileInputStream.close not throwing is not specified by the API docs. At the time of the post it was customary to elide the clause mentioning that this related to the Sun JDK (now known as Oracle JDK and OpenJDK). It appears that an obscure former reimplementation called Apache Harmony which Android used to use may have had different behaviour. Potentially other implementations, or versions of OpenJDK, may also throw.)

一个人的旅程 2024-07-20 19:13:15

检查调用 close 时会发生什么、异常隐藏对您有何影响以及您可以采取哪些措施:博客文章

An examination of what can happen when calling close, how exception hiding can affect you and what you can do about it: blog post.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文