【问题标题】:BufferedOutputStream not throwing I/O exceptionBufferedOutputStream 不抛出 I/O 异常
【发布时间】:2017-08-22 10:44:43
【问题描述】:

在处理 BufferedOutputStream 时发现,当我们在关闭流后对其进行写入时,它不会抛出 IOException

为了验证我的结果,我检查了FileOutputStream,发现在关闭它后尝试在上面写字时它正在抛出IOException

public class Test {
    public static void main(String[] args) {
        try {
            // Created a byte[] barry1 barry2
            byte[] barry1 = { '1', '3' };
            byte[] barray2 = { '2', '4' };
            OutputStream os = new BufferedOutputStream(
                  new FileOutputStream("abc.txt", false));
            // Writing to stream
            os.write(barry1);
            os.close();
            os.write(barray2); // this suceeds - bug

            os = new FileOutputStream("abc.txt", true);
             //Writing to stream
            os.write(barry1);
            os.close();
            os.write(barray2); // crashes here, correct.
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

有人可以帮助我吗,为什么这种行为不同?

【问题讨论】:

    标签: java file-io fileoutputstream bufferedinputstream


    【解决方案1】:

    在处理 BufferedOutputStream 时发现,当我们在关闭流后对其进行写入时,它不会引发 IOException。

    BufferedOutputStream 代码没有那种检查——但FileOutputStream 也没有。在这两种情况下,只有当 IO 实际写入磁盘时,操作系统才会“抛出”IOException。检测流已关闭的不是 Java 代码。顺便说一句,这可能意味着一些本机实现根本不会抛出。

    FileOutputStreamBufferedOutputStream 相比,在os.write(...) 上抛出异常的原因是它立即将 IO 写入底层原生层。如果您在os.write() 之后向BufferedOutputStream 添加os.flush() 调用,那么您将看到相同的异常,因为这会强制其内部缓冲区被写出。

    OutputStream os = new BufferedOutputStream(new FileOutputStream("abc.txt", false));
    os.write(barry1);
    os.close();
    os.write(barray2); // this suceeds – unfortunate behavior
    os.flush();  // adding this line throws an IOException
    

    在查看BufferedOutputStreamclose() 方法(实际上在FilterOutputStream 基类中)时,您可以看到输出流没有设置为null 或任何东西:

    public void close() throws IOException {
        try {
          flush();
        } catch (IOException ignored) {
        }
        out.close();
    }
    

    我也不喜欢它在这里关闭时忽略 IOExceptions 的事实。哇。这告诉我,我们应该始终在 close() 之前手动调用 flush(),这是我特别不这样做的模式。

    现在将该代码与BufferedWriter.close() 进行比较:

    public void close() throws IOException {
        synchronized (lock) {
            if (out == null) {
                return;
            }
            try {
                flushBuffer();
            } finally {
                out.close();
                out = null;   // good doggie
                cb = null;
            }
        }
    }
    

    BufferedWriter.close() 不吃异常并将委托的Writer 设置为null。更好的海事组织。

    【讨论】:

    • 对此答案+1。在我尝试调用 outputteam.flush() 之前,我也有同样的疑问。当输出流关闭时,该调用立即抛出 IOException。
    【解决方案2】:

    因为BufferedOutputStream 将字节写入其内部字节缓冲区,然后在调用时写入底层输出流,所以如果在os.write(c); 之后调用flush,它会抛出异常,但是这里你尝试在文件流关闭后直接写入,因此出现异常,这里不足为奇

    【讨论】:

    • 不,我认为当 that 关闭时写信给BufferedOutputStream(不是FileOutputStream)不会引发异常,这仍然令人惊讶。我可以理解 OP 是否正在关闭下面的 FileOutputStream,但我希望 BufferedOutputStream 也会进行检查。
    • 哇,来自@JonSkeet 的支持评论... :) 先生,请检查
    【解决方案3】:

    检查 JDK 代码后发现 BufferedOutputStream 中缺少 ensureOpen() 方法,该方法会引发 IOException 并显示“Stream closed”的详细消息。据我了解,这一定是存在的。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-01-17
      • 1970-01-01
      • 2021-08-23
      • 2013-01-07
      • 2011-12-29
      • 1970-01-01
      • 2020-02-21
      相关资源
      最近更新 更多