From Gossip@Openhome

Java Gossip: BufferedInputStream、 BufferedOutputStream

在介紹 FileInputStream、 FileOutputStream的 例子中,您使用了一個陣列來作為資料讀入的緩衝區,以檔案存取為例的話,您知道磁碟存取的速度是遠低於記憶體中的資料存取速度,為了減少對磁碟的存取 ,可以一次讀入一定長度的資料,而寫入時也是一次寫入一定長度的資料,這可以增加資料存取的效率。

BufferedInputStream與BufferedOutputStream可以為InputStream類的物件增加緩衝區功能,使用它們,您無需自行設計緩衝區。

BufferedInputStream的資料成員buf是個位元陣列,可查閱標準API原始碼瞭解預設大小,當讀取資料來源時,例如檔案, BufferedInputStream會儘量將buf填滿,當使用read()方法時,實際上是先讀取buf中的資料,而不是直接對資料來源作讀取,當buf中的資料不足時,BufferedInputStream才會再從資料來源中提取資料。

BufferedOutputStream的資料成員buf是個位元陣列,
可查閱標準API原始碼瞭解預設大小,當寫入資料時,會先將資料存至buf中,當buf已滿時才會一次將資料寫至目的地,而不是每次寫入都對目的地作寫入。

將上一個主題的範例作個改寫,這次不用自行設定緩衝區並進行判斷了,使用BufferedInputStream、 BufferedOutputStream讓程式看來簡單一些,也比較有效率:

  • BufferedStreamDemo.java
package onlyfun.caterpillar;

import java.io.*;

public class BufferedStreamDemo {
public static void main(String[] args) {
try {
byte[] data = new byte[1];
File srcFile = new File(args[0]);
File desFile = new File(args[1]);

BufferedInputStream bufferedInputStream =
new BufferedInputStream(
new FileInputStream(srcFile));
BufferedOutputStream bufferedOutputStream =
new BufferedOutputStream(
new FileOutputStream(desFile));

System.out.println("複製檔案:" +
srcFile.length() + "位元組");
while(bufferedInputStream.read(data) != -1) {
bufferedOutputStream.write(data);
}

// 將緩衝區中的資料全部寫出
bufferedOutputStream.flush();

// 關閉串流
bufferedInputStream.close();
bufferedOutputStream.close();
}
catch(ArrayIndexOutOfBoundsException e) {
System.out.println(
"using: java UseFileStream src des");
e.printStackTrace();
}
catch(IOException e) {
e.printStackTrace();
}
}
}

為了確保緩衝區中的資料一定被寫出,建議最後執行flush()將緩衝區中的資料全部寫出目的串流中。

BufferedInputStream、BufferedOutputStream並沒有改變來源InputStream或目的 OutputStream的行為,讀入或寫出時的動作還是InputStream、OutputStream負責, BufferedInputStream、BufferedOutputStream只是在這之前動態的為它們加上一些功能(像是緩衝區功能),在這邊是 以檔案存取串流為例,實際上您可以在其它串流物件上加上BufferedInputStream、BufferedOutputStream功能。