BufferedInputStream 是 Java IO 體系中用於提升讀取效率的緩衝輸入流,它繼承自 FilterInputStream,通過內部維護一個字節數組緩衝區(默認 8192 字節),將底層輸入流的數據分批讀入內存,後續的 read() 操作直接從緩衝區獲取數據,避免頻繁訪問磁盤或網絡,顯著提高 I/O 性能。此外,它還支持 mark() 和 reset() 標記重置功能,便於在流中回退。
private static int defaultBufferSize = 8192; // 默認緩衝區大小
protected volatile byte buf[]; // 緩衝區數組
protected int count; // 緩衝區中有效數據的字節數
protected int pos; // 當前讀取位置索引
protected int markpos = -1; // 標記位置,-1 表示無標記
protected int marklimit; // 標記最大限制
其中 buf 配合 AtomicReferenceFieldUpdater 實現多線程下的原子性更新。
fill() 是填充緩衝區的關鍵邏輯,根據標記狀態和緩衝區剩餘空間分為五種情況處理:
pos 歸零,從底層流讀取新數據填滿緩衝區。System.arraycopy 保留標記位置到末尾的數據移至緩衝區頭部,騰出空間繼續讀取。markpos = -1),重置 pos = 0,丟棄舊數據重新讀取。pos 開始讀取補充數據。這種設計兼顧了標記回退需求與內存佔用控制,marklimit 防止無限擴容導致 OOM。
public class BufferedInputStreamDemo {
public static void main(String[] args) {
File file = new File("bufferedinputstream.txt");
try (BufferedInputStream bis = new BufferedInputStream(
new FileInputStream(file), 512)) {
// 讀取前 5 個字節
for (int i = 0; i < 5; i++) {
if (bis.available() >= 0) {
int b = bis.read();
System.out.printf("%d : 0x%s%n", i, Integer.toHexString(b));
}
}
// 標記當前位置(第 6 個字節),marklimit 1024
bis.mark(1024);
bis.skip(22); // 跳過 22 字節
byte[] buf = new byte[5];
bis.read(buf, 0, 5);
System.out.println("str1=" + new String(buf)); // 輸出 01234
bis.reset(); // 回退到標記處
bis.read(buf, 0, 5);
System.out.println("str2=" + new String(buf)); // 輸出 fghij
} catch (IOException e) {
e.printStackTrace();
}
}
}
測試文件內容:abcdefghijklmnopqrstuvwxyz\n0123456789\nABCDEFGHIJKLMNOPQRSTUVWXYZ
輸出結果驗證了標記/重置機制:先讀 a~e,標記 f,跳過後讀 0~4,重置後讀 f~j。
BufferedInputStream 通過緩衝區減少物理讀取次數,配合 mark/reset 提供隨機訪問能力,是處理大文件、網絡流的首選裝飾器。理解 fill() 的五種分支邏輯,有助於排查緩衝區滿、標記失效等邊界問題。