BufferedOutputStream 没有抛出 I/O 异常

BufferedOutputStream not throwing I/O exception

在处理 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();
        }
    }
}

有人可以帮我解决这个问题吗,为什么这种行为不同?

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

While working on BufferedOutputStream found it does not throw an IOException when we wrote on it after closing the stream.

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

FileOutputStream 相对于 BufferedOutputStreamos.write(...) 上抛出异常的原因是它立即将 IO 写入底层本机层。如果在 os.write() 之后添加对 BufferedOutputStreamos.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基class中),可以看到输出流没有设置为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。海事组织好多了。

检查 JDK 代码后发现 BufferedOutputStream 中缺少 ensureOpen() 抛出带有详细消息 "Stream closed" 的 IOException 的方法。根据我的理解,这一定在那里。