一、最簡單的「一次性讀完」代碼(適合小文件)
- File file = new File(fileName);
- InputStream in = new FileInputStream(file);
- byte[] bytes = new byte[in.available()]; // 獲取文件字節數
- in.read(bytes); // 一次性讀入數組
- in.close();
- // 處理 bytes...
二、關鍵點解析
in.available():返回「當前可不阻塞讀取的字節數」。對本地文件通常等於文件大小,但對網絡流、壓縮流不準確。
read(byte[]):嘗試填滿數組,返回實際讀取字節數(應檢查返回值)。
- 記得關流:建議用 try-with-resources 自動關閉。
三、大文件為什麼不能這樣寫?
- OOM 風險:10GB 文件直接
new byte[10GB] 直接爆堆。
available() 不可靠:某些流實現返回 0 或剩餘緩衝區大小,而非文件總長。
四、大文件正確姿勢:分塊讀取 / 流式處理
- // 固定緩衝區 8KB
- try (InputStream in = new FileInputStream(file)) {
- byte[] buffer = new byte[8192];
- int len;
- while ((len = in.read(buffer)) != -1) {
- // 處理 buffer[0..len-1]
- process(buffer, len);
- }
- }
五、其他常見讀取方式對比
| 場景 | 推薦方式 | 關鍵類 |
| 文本文件按行讀 | BufferedReader.readLine() | Files.newBufferedReader / BufferedReader |
| 小文件一次性讀字符串 | Files.readString(path) (Java 11+) | Files |
| 小文件一次性讀字節 | Files.readAllBytes(path) | Files |
| 大文件流式處理 | Files.newInputStream(path) + 緩衝區循環 | Files / InputStream |
| 內存映射 (超大文件隨機讀) | FileChannel.map() | MappedByteBuffer |
六、總結
- 小文件(< 100MB):
Files.readAllBytes 最簡潔。
- 文本處理:
Files.lines(path) 流式按行處理(Java 8+)。
- 大文件/未知大小:固定緩衝區循環
read(buffer),絕不一次性載入內存。
- 始終使用
try-with-resources 保證資源釋放。