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

Java IO 流體系深度解析(二):位元組流完整指南與最佳實踐

     編輯:Java 綜合教學

Java IO 流體系深度解析(二):位元組流完整指南與最佳實踐

上一節介紹了 Java 流的基本概念,本節系統講解以二進制位元組方式讀寫文件的核心流類別,包括節點流、裝飾流、緩衝流及實用工具方法,助你構建高效、健壯的 IO 代碼。

一、核心類別體系概覽

類別類型用途
InputStream / OutputStream抽象基類定義流操作規範,面向流編程的參數類型
FileInputStream / FileOutputStream節點流文件為源/目的地的基礎讀寫
ByteArrayInputStream / ByteArrayOutputStream節點流內存位元組數組為源/目的地,動態擴容
DataInputStream / DataOutputStream裝飾流按基本類型、字符串讀寫(非純位元組)
BufferedInputStream / BufferedOutputStream裝飾流提供 8KB 默認緩衝,大幅提升單位元組讀寫性能

二、InputStream 核心方法詳解

1. 基本讀取

public abstract int read() throws IOException;
// 讀取單個位元組,返回 0-255,流末尾返回 -1,無數據時阻塞

2. 批量讀取(推薦)

public int read(byte[] b) throws IOException
public int read(byte[] b, int off, int len) throws IOException
// 實際讀取數可能小於數組長度,返回實際讀取位元組數;流末尾返回 -1

3. 進階操作

  • skip(long n):跳過 n 個位元組,返回實際跳過數,效率優於讀取後丟棄。
  • available():返回可無阻塞讀取的位元組估算值,網絡流中常用於判斷何時讀取。
  • mark(int readlimit) / reset() / markSupported():支持標記/重置功能,BufferedInputStream 和 ByteArrayInputStream 支持,文件流不直接支持。

4. 關閉流

close() 必須在 finally 塊調用,釋放文件句柄等系統資源。

三、OutputStream 核心方法

1. 基本寫入

public abstract void write(int b) throws IOException;
// 僅寫入低 8 位

2. 批量寫入

public void write(byte[] b) throws IOException
public void write(byte[] b, int off, int len) throws IOException

3. 刷新與關閉

  • flush():將緩衝區數據推向下游(如操作系統內核緩衝),FileOutputStream 無緩衡,調用無效果。
  • close():隱式調用 flush() 後釋放資源。
注意:FileOutputStream.getFD().sync() 才能強制數據落盤,普通 flush() 僅交給 OS。

四、文件流構造與陷阱

FileOutputStream

new FileOutputStream(file, true) // true = 追加模式,false/無參 = 覆蓋模式

無寫權限拋 SecurityException;路徑指向目錄拋 FileNotFoundException。

FileInputStream

文件必須存在且可讀,否則拋異常。

五、ByteArrayOutputStream:動態內存緩衝

  • 無需預知數據大小,內部位元組數組指數級擴容(初始 32 字節)。
  • 核心方法:toByteArray()、toString(charset)、writeTo(OutputStream)、reset() 重用內存。

讀取未知大小文件最佳實踐:

InputStream input = new FileInputStream("hello.txt");
ByteArrayOutputStream output = new ByteArrayOutputStream();
byte[] buf = new byte[1024];
int len;
while ((len = input.read(buf)) != -1) {
    output.write(buf, 0, len);
}
String content = output.toString("UTF-8");

六、DataInputStream / DataOutputStream:類型化讀寫

裝飾任意流,提供 writeInt、writeDouble、writeUTF 等方法,按大端序寫入二進制。配合 BufferedOutputStream 使用性能最佳:

DataOutputStream out = new DataOutputStream(
    new BufferedOutputStream(new FileOutputStream("data.dat")));

七、BufferedInputStream / BufferedOutputStream:必加裝飾

  • 默認 8KB 緩衝區,極大減少系統調用次數。
  • 幾乎所有文件流操作都應外層包裝緩衝流。
  • BufferedInputStream 額外支持 mark/reset。

八、實用工具方法(可直接納入項目公共庫)

1. 流拷貝

public static void copy(InputStream in, OutputStream out) throws IOException {
    byte[] buf = new byte[4096];
    int len;
    while ((len = in.read(buf)) != -1) out.write(buf, 0, len);
}

2. 文件讀為位元組數組

public static byte[] readFileToByteArray(String path) throws IOException {
    try (InputStream in = new FileInputStream(path);
         ByteArrayOutputStream out = new ByteArrayOutputStream()) {
        copy(in, out);
        return out.toByteArray();
    }
}

3. 位元組數組寫入文件

public static void writeByteArrayToFile(String path, byte[] data) throws IOException {
    try (OutputStream out = new FileOutputStream(path)) {
        out.write(data);
    }
}
生產環境建議直接引入 Apache Commons IO(IOUtils.copy()、FileUtils.readFileToByteArray() 等),經過大規模驗證,更健壯。

九、小結與預告

  • 位元組流適用於圖片、視頻、序列化數據等二進制場景。
  • 不適用於文本處理(無編碼概念、無按行讀取)。
  • 下一節將講解 字符流,解決文本文件讀寫痛點。

----------------

未完待續,關注微信公眾號「老馬說編程」獲取最新文章,從入門到高級,深入淺出探索 Java 編程本質。

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