在 Java 開發中,將檔案轉換為位元組陣列(byte[])是常見需求,例如透過 HTTP 傳輸二進位資料、檔案加密、或儲存至資料庫的 BLOB 欄位。本文將詳細介紹使用 FileInputStream 與 ByteArrayOutputStream 實現檔案到位元組陣列的轉換,並說明關鍵細節與最佳實踐。
FileInputStream 是 InputStream 的子類,專門用於從檔案系統讀取原始位元組資料。建構子接受 File 物件或檔案路徑字串:
File file = new File("path/to/your/file.dat");
FileInputStream fis = new FileInputStream(file);
ByteArrayOutputStream 在記憶體中建立可動態擴充的緩衝區,所有寫入的資料皆暫存於此,最終可透過 toByteArray() 取得完整位元組陣列。
FileInputStream fis = null;
ByteArrayOutputStream bos = null;
try {
File file = new File("filePath");
fis = new FileInputStream(file);
bos = new ByteArrayOutputStream();
byte[] buffer = new byte[1024]; // 1KB 緩衝區
int bytesRead;
while ((bytesRead = fis.read(buffer)) != -1) {
// 關鍵:必須指定實際讀取長度 bytesRead
bos.write(buffer, 0, bytesRead);
}
byte[] fileBytes = bos.toByteArray();
// 後續業務邏輯處理 fileBytes...
} catch (IOException e) {
e.printStackTrace();
} finally {
// 資源關閉建議使用 try-with-resources (Java 7+)
try { if (fis != null) fis.close(); } catch (IOException ignored) {}
try { if (bos != null) bos.close(); } catch (IOException ignored) {}
}
write(buffer, 0, len)?ByteArrayOutputStream 的 write 方法有三種重載:
write(int b) - 寫入單一位元組write(byte[] b) - 寫入整個陣列write(byte[] b, int off, int len) - 寫入陣列指定範圍陷阱警示:若直接使用 bos.write(buffer),當最後一次讀取不足 1024 位元組時,會將緩衝區剩餘的舊資料一併寫入,導致輸出陣列長度大於實際檔案大小。因此必須使用第三種形式,配合 fis.read(buffer) 的回傳值 len,精確寫入實際讀取的位元組數。
Java 9 引入 InputStream.transferTo(OutputStream),可大幅簡化代碼:
try (FileInputStream fis = new FileInputStream(file);
ByteArrayOutputStream bos = new ByteArrayOutputStream()) {
fis.transferTo(bos);
byte[] fileBytes = bos.toByteArray();
}
OutOfMemoryError。大檔案建議使用串流分段處理或 MappedByteBuffer。finally 區塊或使用 try-with-resources 關閉串流。掌握 FileInputStream 搭配 ByteArrayOutputStream 的正確讀寫模式,是 Java 檔案處理的基礎技能。理解緩衝區長度控制的細節,能避免資料損壞與記憶體浪費,為後續的網路傳輸、加密解密、序列化等操作奠定堅實基礎。