1.什麼是緩衝流,有什麼作用?
這裏需要說明一點小知識,在對硬盤進行讀寫操作時,一個完整的文件的讀寫速率要遠遠高於同樣大小的散文件的讀寫速率。這是因爲散文件需要不斷地訪問、關閉硬盤,極大地浪費了時間,緩衝流也是同樣原理。
緩衝流基於IO流,在IO流中使用。顧名思義,它是一個緩衝內存,即在對外部設備中的文件進行讀寫操作時,先創建一定內存,然後再在這部分內存中讀寫數據,讀寫完成後再統一訪問該設備。使用緩衝流減少了對外部硬盤的訪問次數,通過一系列測試證明,使用緩衝流可成幾十倍甚至上百倍地提高讀寫效率,尤其是對於非文本文件的操作。
【重點】
- 所有的緩衝流都只是提供緩存,沒有任何的讀取、寫入文件能力,需要對應的I、O流來進行輸入輸出。
- 在創建緩衝流流對象時,需要傳入的參數爲——對應的輸入流對象或輸出流對象。
- 底層會提供一個默認大小的緩衝數組,用於提高效率
2.分類
因緩衝流基於IO流,而IO流分別按走向、操作單元可分爲輸入、輸出流,字節、字符流,因此緩衝流也有同樣的分類:
字節輸入緩衝流: BufferedInputStream
字節輸出緩衝流: BufferedOutputStream
字符輸入緩衝流: BufferedReader
字符輸出緩衝流: BufferedWrite
2.1 字節緩衝流
2.1.1【輸入】字節緩衝流
BufferedInputStream(InputStream inputStream);
形參爲一個字節輸入流基類對象。當然也可以傳入InputStream子類對象
【效率問題】
-
1.在BufferedInputStream底層會默認提供一個容量爲8KB的byte類型緩衝數組
-
2.fill方法是一個操作核心
a.從硬盤中讀取數據,讀取的數據容量和緩衝數組容量一致 b.所有的read方法,都是從緩衝數組中讀取數據 c.每一次讀取數據之前,都會檢查緩衝區內是否有數據,如果沒有,fill方法執行,填充數據,
-
3.利用緩衝,fill方法,可以極大地降低CPU通過內存訪問硬盤的次數,同時程序操作的數據是在內存中進行交互的。
2.1.2【輸出】字節緩衝流
BufferedOutputStream(OutputStream outputStream);
形參爲一個字節輸出流基類對象。也可以傳入OutputStream子類對象
【效率問題】
- 1.同BufferedInputStream,默認8kb的byte類型緩衝數組
- 2.寫入文件時,同樣是先寫入內存的8kb緩衝數組中,然後再統一保存到硬盤文件中
- 3.如果默認容量8kb不夠用,會直接flush緩衝區,數據保存到硬盤中,同時清空整個緩衝區,重複使用。
- 4.在BufferedOutputStream關閉時,首先會調用flush方法,保存數據到文件,清空緩衝區,並且規劃緩衝區佔用內存,同時關閉緩衝流使用的字節輸出流。
代碼演示(拷貝效率)
有緩衝數組的方法:
總耗時1716 ms
public static void useBuffered() {
BufferedInputStream bis = null;
BufferedOutputStream bos = null;
try {
bis = new BufferedInputStream(new FileInputStream(new File("D:/aaa/2.txt")));
bos = new BufferedOutputStream(new FileOutputStream(new File("D:/aaa/buffered.txt")));
int content = -1;
while ((content = bis.read()) != -1) {
bos.write(content);
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
if (bos != null) {
try {
bos.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if (bis != null) {
try {
bis.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
無緩衝數組的方法:
總耗時531000
public static void copy() {
FileInputStream fis = null;
FileOutputStream fos = null;
try {
fis = new FileInputStream("D:/aaa/2.txt");
fos = new FileOutputStream("D:/aaa/copy.txt");
int content = -1;
while ((content = fis.read()) != -1) {
fos.write(content);
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
if (fos != null) {
try {
fos.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if (fis != null) {
try {
fis.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
2.2字符緩衝流
字符緩衝流基本同於字節緩衝流
輸入字符緩衝流: BufferedReader
輸出字符緩衝流: BufferedWrite
【注意】
- 1.字符緩衝輸入流,底層默認提供一個有8192個元素的緩衝字符數組,而且使用fill方法從硬盤中讀取數據填充緩衝數組
- 2.字符緩衝輸出流,底層有默認提供一個有8192個元素的緩衝字符數組,使用flush方法將緩衝數組中的內容寫入到硬盤當中。
- 3.使用緩衝數組之後,程序在運行的大部分時間內,都是內存和內存之間的數據交互,降低了CPU通過內存操作硬盤的次數,效率高
- 4.關閉字符緩衝流,都會首先釋放對應的緩衝數組內存,然後關閉對應的字符輸入流、字符輸出流。
- 5.字符緩衝輸入流中 String readLine(); 讀取一行數據
- 6.字符緩衝輸出流中 void newLine(); 換行