首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計疑難解答

Java FileInputStream 讀取機制詳解:緩衝區、len 參數與 StringBuilder 追加原理

     編輯:程式設計疑難解答

代碼片段

byte[] bytes = new byte[1024*1024*10]; // 10MB 緩衝區
int len = -1;
StringBuffer buf = new StringBuffer();
while ((len = in.read(bytes)) != -1) {
    buf.append(new String(bytes, 0, len));
}

核心疑問

文件內容 01234,為何輸出不是 001012012301234(累積歷史內容)?

機制解析

1. read(byte[] b) 契約

  • 嘗試讀取最多 b.length 字節。
  • 返回實際讀取字節數 len(-1 表示 EOF)。
  • 數據寫入 b[0] ~ b[len-1],**不清理剩餘位置**。

2. 為何不累積?

每次循環 in.read(bytes) 都會**覆蓋** bytes[0..len-1] 為最新讀取的數據。舊數據被新數據覆蓋,不再存在。new String(bytes, 0, len) 僅取本次有效區間,故無歷史殘留。

3. 最後一次讀取 len < bytes.length 時

若文件大小非緩衝區整數倍,最後一次 len 小於緩衝區大小。bytes[len...] 仍保留上次數據,**但 new String(bytes, 0, len) 截取長度為 len,舊數據不參與構造**,故安全。

圖解讀取過程

文件: [0][1][2][3][4]  (5字節)
緩衝區大小: 10 字節

第1次 read: len=5
bytes = [0][1][2][3][4][?][?][?][?][?]
new String(bytes,0,5) → "01234"
append → buf = "01234"

第2次 read: len=-1 (EOF) 循環結束

最佳實踐建議

  • 緩衝區大小 8KB~64KB 即可(4096 或 8192),10MB 過大易致 OOM。
  • 優先用 try-with-resources 自動關閉流(Java 7+)。
  • 文本文件直接用 Files.readAllLines 或 BufferedReader 逐行處理,避免手動編碼轉換。

總結

InputStream.read(byte[]) 每次**覆蓋緩衝區頭部**,len 标记有效長度。new String(bytes, 0, len) 精確截取本次有效數據,**不會累積歷史內容**。理解「緩衝區復用 + 長度截取」模式,是掌握 Java IO 流的關鍵。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved