這篇來學習Java中利用緩存區來進行檔案讀寫操作。一個輸入流緩存(BufferedInputStream)和輸出流緩存(BufferedOutputStream),了解了其中一個,另外一個就也了解了。下面,我們先看看BufferedInputStream這個類的API介紹和源碼實作。
1.BufferedInputStream的原理
在這個類的API中,可以看到這麼一句描述的話:在建立
BufferedInputStream
時,會建立一個内部緩沖區數組。在讀取或跳過流中的位元組時,可根據需要從包含的輸入流再次填充該内部緩沖區,一次填充多個位元組。那麼,我們就看看它的底層實作原理。打開
BufferedInputStrea源碼,可以找到這麼一個成員變量:
DEFAULT_BUFFER_SIZ=8192,這個表示緩沖區大小是8kb而且,底層是一個位元組數組實作的。
2.BufferInputStream和BufferedOutputStream實作檔案拷貝代碼
我們直接來一個簡單代碼,然後來分析注意點和總結特點。
package io;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
public class Demo4_BufferCopy {
public static void main(String[] args) throws IOException {
FileInputStream fis = new FileInputStream("C:\\Users\\Administrator\\Desktop\\jenkins.war");
FileOutputStream fos = new FileOutputStream("copy.war");
//建立緩沖區,對輸入流進行包裝
BufferedInputStream bis = new BufferedInputStream(fis);
//建立緩沖區,對輸出流進行包裝
BufferedOutputStream bos = new BufferedOutputStream(fos);
int b;
while ( (b = bis.read()) != -1) {
bos.write(b);
}
//關閉輸入流緩沖區
bis.close();
//關閉輸出流緩存區
bos.close();
}
}
運作之後,重新整理Eclipse項目,可以看到copy.war檔案複制成功。注意上面,之後關閉的是輸入流緩沖區對象和輸出流緩沖區對象,而不是輸入流和輸出流對象,這點和前面有一點差別。原因也很簡單,緩沖區對象本來就是包裝了對應的輸入流或者輸出流,關閉了緩沖區,自然把包裝裡面對象也給一同關閉。
3.為什麼要加入緩存思想
這裡面涉及到一個裝飾器和設計模式的概念,後面我們來學習。很明顯,位元組流一次讀寫一個數組的速度肯定要比一次讀寫一個位元組的速度要快,效率高。緩沖區底層就是數組,這個我們在StringBuffer這個類也可以找到這種設計思想。
4.BufferedInputStream緩沖區具體原理
原理是BufferedInputStream底層用了一個數組,預設大小是8192個位元組,也就是BufferedInputStream一次性會從檔案讀取8192個位元組,然後傳回給程式一個位元組,程式在讀取8192個位元組之前不需要再次去通路和讀取檔案,直接從緩沖區讀。直到緩沖區所有的都讀取過,然後再去讀取8192個位元組,一直這樣進行下去,直到任務結束。同樣的BufferedOutputStream也是内置一個數組,預設大小也是8192位元組。程式向流中寫出位元組時,不會直接寫到檔案,而是先寫入到緩沖區,直到緩沖區寫滿,BufferedInputStream才會一次性把資料寫入到檔案中。