首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Java ByteArray 輸入輸出流詳解:內存字節數組的高效讀寫

     編輯:Java 相關知識

前言

ByteArrayInputStream 與 ByteArrayOutputStream 將字節數組作為內存流來源/目的地,實現「內存↔流」零拷貝轉換,廣泛用於單元測試、序列化緩衝、圖片/文件內存處理。本文詳解兩大類核心 API 並附完整可運行示例。

一、ByteArrayInputStream:字節數組輸入流

1.1 核心結構

  • 內部封裝 byte[] buf 作為緩衝區。
  • pos:下一個待讀字節索引;mark:標記位置;count:有效數據長度。
  • 繼承 InputStream,實現 read()、skip()、mark/reset 等標準接口。

1.2 關鍵構造器

// 使用整個數組
ByteArrayInputStream(byte[] buf)
// 使用數組片段 offset/length
ByteArrayInputStream(byte[] buf, int offset, int length)

1.3 核心方法演示

byte[] data = "abcdefghijklmnopqrstuvwxyz".getBytes();
ByteArrayInputStream bis = new ByteArrayInputStream(data);

// 1. 讀取前 5 字節
for (int i=0; i<5; i++) System.out.printf("%d: 0x%X%n", i, bis.read());
// 輸出: 0:61(a) 1:62(b) 2:63(c) 3:64(d) 4:65(e)

// 2. mark(0) 標記當前位置 (f)
bis.mark(0);  // 參數 readlimit 在此類中無實際限制作用

// 3. skip(5) 跳過 5 字節 → 位置移至 k
bis.skip(5);

// 4. 讀取 5 字節到數組 → klmno
byte[] buf = new byte[5];
bis.read(buf, 0, 5);
System.out.println(new String(buf)); // klmno

// 5. reset() 回到 mark 位置 (f)
bis.reset();

// 6. 再讀 5 字節 → fghij
bis.read(buf, 0, 5);
System.out.println(new String(buf)); // fghij

1.4 關鍵特性

  • 不阻塞:內存數據現成,read() 立即返回,無 I/O 等待。
  • markSupported() 返回 true:支持任意長度標記/重置,readlimit 參數被忽略。
  • 線程不安全:多線程共享同一實例需外部同步。

二、ByteArrayOutputStream:字節數組輸出流

2.1 核心結構

  • 內部動態 byte[] buf,初始 32 字節,寫入超過容量自動擴容(2倍)。
  • count:當前有效字節數。
  • 繼承 OutputStream,實現 write()、toByteArray()、toString()、writeTo(OutputStream)。

2.2 核心方法演示

ByteArrayOutputStream bos = new ByteArrayOutputStream();

// 1. 寫入單字節 A/B/C (0x41/42/43)
bos.write(0x41); bos.write(0x42); bos.write(0x43);
System.out.println(bos); // ABC

// 2. 批量寫入數組片段 defgh (索引3長度5)
byte[] src = "abcdefghijklmnopqrstuvwxyz".getBytes();
bos.write(src, 3, 5);
System.out.println(bos); // ABCdefgh

// 3. 獲取長度與字節數組
int size = bos.size();        // 8
byte[] result = bos.toByteArray(); // [65,66,67,100,101,102,103,104]

// 4. 輸出到另一個流
ByteArrayOutputStream bos2 = new ByteArrayOutputStream();
bos.writeTo(bos2);
System.out.println(bos2); // ABCdefgh

2.3 關鍵特性

  • 自動擴容:無需預估大小,適合未知長度數據累積。
  • toString() 使用平台默認編碼:生產環境建議 toString(StandardCharsets.UTF_8)(Java 9+)或 new String(buf, 0, count, "UTF-8")。
  • 無需關閉:close() 空實現,不釋放內存,GC 回收數組。
  • 線程不安全:同 ByteArrayInputStream。

三、典型應用場景

場景用法
單元測試 Mock 流new ByteArrayInputStream(json.getBytes()) 模擬網絡響應
序列化緩衝對象 → ByteArrayOutputStream → byte[] → Redis/DB
圖片內存處理讀取文件 → ByteArrayInputStream → ImageIO.read → 處理 → ByteArrayOutputStream → 上傳
壓縮/加密中間緩衝GZIPOutputStream 包裝 ByteArrayOutputStream 直接壓縮到內存
日誌/指標聚合多線程寫入各自 ByteArrayOutputStream,定期合併刷盤

四、避坑指南

  1. 大數據慎用:內存雙份(數組+流),超大文件易 OOM,改用臨時文件或管道流。
  2. 編碼顯式化:toString("UTF-8") 避免跨平台亂碼。
  3. 及時釋放引用:用完置 null,助 GC 回收大數組。
  4. 非線程安全:多線程環境用 ByteArrayOutputStream 時加鎖或用 ThreadLocal 隔離。

五、總結

ByteArrayInputStream 讓字節數組具備流讀取能力,ByteArrayOutputStream 讓流輸出聚合為字節數組。兩者配合實現「內存流」閉環,是 Java IO 體系中輕量級、高性能的內存數據交換基石。

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