天天看點

Java IO:BufferedOutputStream使用詳解及源碼分析

使用方法

  BufferedOutputStream繼承于FilterOutputStream,提供緩沖輸出流功能。緩沖輸出流相對于普通輸出流的優勢是,它提供了一個緩沖數組,隻有緩沖數組滿了或者手動flush時才會向磁盤寫資料,避免頻繁IO。核心思想是,提供一個緩沖數組,寫入時首先操作緩沖數組。

方法介紹

  BufferedOutputStream提供的API如下:

//構造函數
BufferedOutputStream(OutputStream out) //預設緩沖數組大小為8192
BufferedOutputStream(OutputStream out, int size)

synchronized void     close() //關閉
synchronized void     flush() //刷盤
synchronized void     write(byte[] b, int off, int len) //向輸出流寫資料
synchronized void     write(int b)
           

使用示例

public void testBufferedOutput() {
    try {
        final byte [] letters = {'a','b','c','d','e','f','g','h','i','j','k','l','m','n'};
        /*
         *建立檔案輸出流out,緩沖區大小為8
         */
        OutputStream out = new BufferedOutputStream(new FileOutputStream(new File("buff.txt")), );
        /*将letters前6個字元寫入到輸出流*/
        out.write(letters,  ,);
        /*此時不會寫入任何資料到磁盤檔案*/
        readFile();
        /*繼續寫入4個字元*/
        for (int i = ; i < ; i++) {
            out.write('g' + i);
        }
        /*此時隻會寫入8個字元到磁盤檔案*/
        readFile();
        /*此時會把所有内容寫入磁盤檔案*/
        out.flush();
        readFile();
    } catch (Exception e) {
        e.printStackTrace();
    }
}

private void readFile() {
    try {
        InputStream in = new FileInputStream("buff.txt");
        byte [] bytes = new byte[];
        in.read(bytes, , bytes.length);
        System.out.println("檔案中的内容為: "  + new String(bytes));
    } catch (Exception e) {
        e.printStackTrace();
    }
}
           

  運作結果如下:

檔案中的内容為:
檔案中的内容為: abcdefgh
檔案中的内容為: abcdefghij
           

源碼分析

構造方法

  BufferedOutputStream的構造方法有兩個,差別是位元組緩沖數組大小。

/**
 * Creates a new buffered output stream to write data to the
 * specified underlying output stream.
 *
 * @param   out   the underlying output stream.
 */
public BufferedOutputStream(OutputStream out) {
    this(out, );
}

/**
 * Creates a new buffered output stream to write data to the
 * specified underlying output stream with the specified buffer
 * size.
 *
 * @param   out    the underlying output stream.
 * @param   size   the buffer size.
 * @exception IllegalArgumentException if size &lt;= 0.
 */
public BufferedOutputStream(OutputStream out, int size) {
    super(out);
    if (size <= ) {
        throw new IllegalArgumentException("Buffer size <= 0");
    }
    buf = new byte[size];
}
           

write方法

  write方法有兩個重載方法,分别是協定一個位元組的write(int b)和寫入一個位元組數組的write(byte b[], int off, int len)。下面分析第二個方法的源碼。

/**
 * Writes <code>len</code> bytes from the specified byte array
 * starting at offset <code>off</code> to this buffered output stream.
 *
 * <p> Ordinarily this method stores bytes from the given array into this
 * stream's buffer, flushing the buffer to the underlying output stream as
 * needed.  If the requested length is at least as large as this stream's
 * buffer, however, then this method will flush the buffer and write the
 * bytes directly to the underlying output stream.  Thus redundant
 * <code>BufferedOutputStream</code>s will not copy data unnecessarily.
 *
 * @param      b     the data.
 * @param      off   the start offset in the data.
 * @param      len   the number of bytes to write.
 * @exception  IOException  if an I/O error occurs.
 */
public synchronized void write(byte b[], int off, int len) throws IOException {
    if (len >= buf.length) { //如果寫入長度比buf長度長,直接寫入檔案,不走緩沖區
        /* If the request length exceeds the size of the output buffer,
           flush the output buffer and then write the data directly.
           In this way buffered streams will cascade harmlessly. */
        flushBuffer(); //将原有緩沖區内容刷盤
        out.write(b, off, len); //直接寫入檔案
        return;
    }
    if (len > buf.length - count) { //可用空間不足,先刷盤
        flushBuffer();
    }
    System.arraycopy(b, off, buf, count, len); //複制寫入
    count += len;
}
/** Flush the internal buffer */
private void flushBuffer() throws IOException {
    if (count > ) {
        out.write(buf, , count);
        count = ;
    }
}
           

flush方法

/**
 * 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(); //未做任何實作
}
           

參考:

[1] http://www.cnblogs.com/skywang12345/p/io_13.html

[2] http://czj4451.iteye.com/blog/1545159