FileInputStream 是字節輸入流基石,關鍵方法:
int read():讀取單字節,返回 0-255,末尾返回 -1int read(byte[] b):批量讀入字節數組,返回實際讀取字節數int available():返回剩餘可讀字節數(僅適用普通文件)public byte[] readAllBytes(String filePath) throws IOException {
File file = new File(filePath);
try (FileInputStream in = new FileInputStream(file)) {
// 關鍵:available() 獲取文件大小,分配精確數組
byte[] bytes = new byte[in.available()];
int read = in.read(bytes);
if (read != bytes.length) {
throw new IOException("讀取不完整: 預期 " + bytes.length + " 實際 " + read);
}
return bytes;
} // try-with-resources 自動關閉
}
| 場景 | 是否適用 | 說明 |
|---|---|---|
| 小文件 (< 10MB) | ✅ 完美 | 一次性讀入,代碼簡潔 |
| 大文件 (> 100MB) | ❌ 禁止 | OOM 風險,需分塊讀取/流式處理 |
| 網絡流/管道/設備文件 | ❌ 禁止 | available() 返回 0 或不準確 |
| 需邊讀邊處理 | ❌ 不適用 | 用緩衝流 + 循環 read() |
public void processLargeFile(String filePath, ConsumerchunkHandler) throws IOException { final int BUFFER_SIZE = 8192; // 8KB 緩衝區 try (FileInputStream in = new FileInputStream(filePath); BufferedInputStream bin = new BufferedInputStream(in, BUFFER_SIZE)) { byte[] buffer = new byte[BUFFER_SIZE]; int len; while ((len = bin.read(buffer)) != -1) { // 處理實際讀取的字節 chunkHandler.accept(Arrays.copyOf(buffer, len)); } } }
public void readWithNIO(String filePath) throws IOException {
try (FileChannel channel = FileChannel.open(Paths.get(filePath), StandardOpenOption.READ)) {
MappedByteBuffer buffer = channel.map(FileChannel.MapMode.READ_ONLY, 0, channel.size());
// 直接操作 buffer,OS 負責頁面調度,不佔用 JVM 堆
}
}
FileReader/BufferedReader小文件用 in.read(new byte[in.available()]) 一行搞定;大文件用緩衝流分塊或 NIO 內存映射;永遠用 try-with-resources 管理資源。