ByteArrayInputStream 類詳解
ByteArrayInputStream
是 Java 中用于從字節數組讀取數據的輸入流,位于 java.io
包。它允許將內存中的字節數組當作輸入流來讀取,是處理內存數據的常用工具。
1. 核心特性
- 內存數據源:從字節數組(
byte[]
)讀取數據 - 無需關閉:
close()
方法為空操作(無系統資源需要釋放) - 線程不安全:多線程訪問需外部同步
- 支持標記/重置:可重復讀取數據(
mark()
和reset()
)
2. 類繼承關系
3. 構造方法
構造方法 | 說明 |
---|---|
ByteArrayInputStream(byte[] buf) | 使用整個字節數組作為數據源 |
ByteArrayInputStream(byte[] buf, int offset, int length) | 使用數組的指定區間 |
4. 核心方法
(1)讀取數據
方法 | 說明 |
---|---|
int read() | 讀取單個字節(返回0-255,-1表示結束) |
int read(byte[] b, int off, int len) | 讀取數據到字節數組 |
long skip(long n) | 跳過指定字節數 |
示例:
byte[] data = {72, 101, 108, 108, 111}; // "Hello"的ASCII碼
ByteArrayInputStream bais = new ByteArrayInputStream(data);int byteRead;
while ((byteRead = bais.read()) != -1) {System.out.print((char) byteRead); // 輸出: Hello
}
(2)流控制
方法 | 說明 |
---|---|
int available() | 返回剩余可讀字節數 |
void mark(int readlimit) | 標記當前位置(readlimit 參數被忽略) |
void reset() | 重置到標記位置(默認是起始位置) |
boolean markSupported() | 始終返回 true (支持標記) |
標記/重置示例:
bais.mark(0); // 標記起始位置
System.out.print((char) bais.read()); // 讀取'H'
bais.reset(); // 重置回起始位置
System.out.print((char) bais.read()); // 再次讀取'H'
5. 使用場景
(1)內存數據處理
byte[] pdfData = generatePdf();
try (ByteArrayInputStream bais = new ByteArrayInputStream(pdfData);PDFParser parser = new PDFParser(bais)) {// 解析PDF數據
}
(2)單元測試模擬輸入
// 模擬用戶輸入
String input = "test\n123\n";
ByteArrayInputStream testInput = new ByteArrayInputStream(input.getBytes());
System.setIn(testInput); // 重定向System.inScanner scanner = new Scanner(System.in);
System.out.println(scanner.nextLine()); // 輸出: test
(3)與其他流配合
byte[] compressedData = getGzipData();
try (ByteArrayInputStream bais = new ByteArrayInputStream(compressedData);GZIPInputStream gzis = new GZIPInputStream(bais)) {// 解壓數據
}
6. 性能優化
(1)批量讀取
byte[] buffer = new byte[1024];
int bytesRead;
while ((bytesRead = bais.read(buffer)) != -1) {process(buffer, 0, bytesRead);
}
(2)避免頻繁創建
// 復用ByteArrayInputStream(調用reset()后重新讀取)
bais.reset();
7. 與 ByteArrayOutputStream 對比
特性 | ByteArrayInputStream | ByteArrayOutputStream |
---|---|---|
方向 | 讀取數據 | 寫入數據 |
數據源 | 已有字節數組 | 動態增長緩沖區 |
關閉需求 | 非必需 | 非必需 |
典型用途 | 解析內存數據 | 收集輸出數據 |
8. 常見問題
(1)數組越界
- 錯誤示例:
byte[] smallArray = new byte[10]; ByteArrayInputStream bais = new ByteArrayInputStream(smallArray, 5, 10); // 拋出IndexOutOfBoundsException
- 解決:確保
offset + length ≤ buf.length
(2)編碼轉換
- 正確方式:
byte[] utf8Bytes = "中文".getBytes("UTF-8"); ByteArrayInputStream bais = new ByteArrayInputStream(utf8Bytes); String text = new String(toByteArray(bais), "UTF-8");
9. 實戰案例
(1)Base64 解碼
String base64 = "SGVsbG8="; // "Hello"的Base64編碼
byte[] decoded = Base64.getDecoder().decode(base64);
ByteArrayInputStream bais = new ByteArrayInputStream(decoded);
// 使用解碼后的數據...
(2)圖像處理
byte[] imageData = getImageBytes();
ByteArrayInputStream bais = new ByteArrayInputStream(imageData);
BufferedImage image = ImageIO.read(bais);
10. 總結
- 適用場景:內存數據解析、測試數據模擬、與其他流配合
- 優勢:無需物理I/O,輕量高效
- 注意:大數據量需考慮內存限制
擴展練習:
- 實現一個方法,將
ByteArrayInputStream
內容復制到ByteArrayOutputStream
- 結合
DataInputStream
讀取結構化二進制數據