BufferedOutputStream 实际上是如何在低级别工作的?
Posted
技术标签:
【中文标题】BufferedOutputStream 实际上是如何在低级别工作的?【英文标题】:How does BufferedOutputStream actually work at a low level? 【发布时间】:2012-03-06 04:14:04 【问题描述】:我了解BufferedOutputStream
背后的理论。字节被写入缓冲区数组,直到它被填满,然后写入(刷新)到底层流 - 因为操作系统调用更少,所以它比逐字节写入更快。
然而,从 BufferedOutputStream
类和方法 (BufferedOutputStream.java) 的实现来看,似乎最终来自缓冲区的字节只是逐字节写入。
我认为是这样的,因为:
在 BufferedOutputStream.write(byte b[], int off, int len) 中有一行 out.write(b, off, len)。由于 out 是 OutputStream 的一个实例,而不是 BufferedOutputStream,它正在调用 OutputStream.write(byte[], int, int)。这又使用 for 循环逐字节写入
请有人澄清实际发生了什么,以及它如何更快?
【问题讨论】:
使用out.write(bytes ,offset, length)
刷新缓冲区是如何逐字节进行的?你能说得更具体点吗?
但是out.write(bytes ,offset, length) 没有调用OutputStream.java 中的write(byte b[], int off, int len) 方法吗?然后哪个使用 for 循环分别写入缓冲区中的每个字节?
OutputStream
是抽象的。大多数子类将使用更有效的版本覆盖此方法。以FileOutputStream 为例。
对Behind the scenes of Java's BufferedInputStream OP 的评论可能会有所帮助。
【参考方案1】:
来自您的链接:
/** Flush the internal buffer */
private void flushBuffer() throws IOException
if (count > 0)
out.write(buf, 0, count);
count = 0;
...
/**
* Flushes this buffered output stream. This forces any buffered
* output bytes to be written out to the underlying output stream.
*
* @exception IOException if an I/O error occurs.
* @see java.io.FilterOutputStream#out
*/
public synchronized void flush() throws IOException
flushBuffer();
out.flush();
如您所见,flush()
将所有缓冲区内容一次性写入底层流,然后级联刷新。 BufferedOutputStream
然后重新实现 write(byte b[], int off, int len)
和 void write(int b)
(类中的核心方法,每次写入都被委托给它),以便写入缓冲区,并在必要时刷新。
【讨论】:
【参考方案2】:代码说明:
79 /** Flush the internal buffer */
80 private void flushBuffer() throws IOException
81 if (count > 0)
82 out.write(buf, 0, count);
83 count = 0;
84
85
这是对所有当前缓冲字节的写入。不是逐字节的。
【讨论】:
但是 write(buf, 0, count) 不能逐字节进行吗? ... for (int i = 0 ; i 【参考方案3】:这个想法是BufferedOutputStream
的用户 不必等待每个字节都被真正发送。即使连接本身很慢,用户也可以将更大的块推送到输出流并继续。所以这边比较快。输出流本身会尽可能快。
【讨论】:
【参考方案4】:当数据被刷新时,它是一个块。
79 /** Flush the internal buffer */
80 private void flushBuffer() throws IOException
81 if (count > 0)
82 out.write(buf, 0, count);
83 count = 0;
84
85
FileOutputStream 和许多其他重写 OutputStream.write() 以有效地处理数据块。
http://www.docjar.com/html/api/java/io/FileOutputStream.java.html
284
285 /**
286 * Writes a sub array as a sequence of bytes.
287 * @param b the data to be written
288 * @param off the start offset in the data
289 * @param len the number of bytes that are written
290 * @param append @code true to first advance the position to the
291 * end of file
292 * @exception IOException If an I/O error has occurred.
293 */
294 private native void writeBytes(byte b[], int off, int len, boolean append)
295 throws IOException;
308 /**
309 * Writes <code>len</code> bytes from the specified byte array
310 * starting at offset <code>off</code> to this file output stream.
311 *
312 * @param b the data.
313 * @param off the start offset in the data.
314 * @param len the number of bytes to write.
315 * @exception IOException if an I/O error occurs.
316 */
317 public void write(byte b[], int off, int len) throws IOException
318 writeBytes(b, off, len, append);
319
【讨论】:
如果 write(buffer, start, len) 未被覆盖,则缓冲区毫无意义。大多数流都会覆盖它。 在 BufferedOutputStream.write(byte b[], int off, int len) 中有 write out.write(b, off, len)。这是指哪个写法? 不是OutputStream.write(byte[], int, int) 吗? 哪个又使用for循环逐字节写入? 如果它被覆盖,通常是这样。例如在FileOutputStream.write(byte[], int, int)
以上是关于BufferedOutputStream 实际上是如何在低级别工作的?的主要内容,如果未能解决你的问题,请参考以下文章
BufferedInputStream与BufferedOutputStream用法简介
Java IO BufferedInputStream 和 BufferedOutputStream
性能:BufferedOutputStream 与 FileWriter
文件流之字节缓冲流(BufferedInputStream BufferedOutputStream)