【问题标题】:How does BufferedOutputStream actually work at a low level?BufferedOutputStream 实际上是如何在低级别工作的?
【发布时间】: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 的评论可能会有所帮助。

标签: java buffer flush bufferedoutputstream


【解决方案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)
      猜你喜欢
      • 2018-04-17
      • 1970-01-01
      • 2019-04-24
      • 1970-01-01
      • 2021-01-21
      • 2011-09-27
      • 2021-12-16
      • 2013-03-14
      • 2021-03-23
      相关资源
      最近更新 更多