使用方法
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 <= 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