上一節介紹了 Java 流的基本概念,本節系統講解以二進制位元組方式讀寫文件的核心流類別,包括節點流、裝飾流、緩衝流及實用工具方法,助你構建高效、健壯的 IO 代碼。
| 類別 | 類型 | 用途 |
|---|---|---|
| InputStream / OutputStream | 抽象基類 | 定義流操作規範,面向流編程的參數類型 |
| FileInputStream / FileOutputStream | 節點流 | 文件為源/目的地的基礎讀寫 |
| ByteArrayInputStream / ByteArrayOutputStream | 節點流 | 內存位元組數組為源/目的地,動態擴容 |
| DataInputStream / DataOutputStream | 裝飾流 | 按基本類型、字符串讀寫(非純位元組) |
| BufferedInputStream / BufferedOutputStream | 裝飾流 | 提供 8KB 默認緩衝,大幅提升單位元組讀寫性能 |
public abstract int read() throws IOException; // 讀取單個位元組,返回 0-255,流末尾返回 -1,無數據時阻塞
public int read(byte[] b) throws IOException public int read(byte[] b, int off, int len) throws IOException // 實際讀取數可能小於數組長度,返回實際讀取位元組數;流末尾返回 -1
skip(long n):跳過 n 個位元組,返回實際跳過數,效率優於讀取後丟棄。available():返回可無阻塞讀取的位元組估算值,網絡流中常用於判斷何時讀取。mark(int readlimit) / reset() / markSupported():支持標記/重置功能,BufferedInputStream 和 ByteArrayInputStream 支持,文件流不直接支持。close() 必須在 finally 塊調用,釋放文件句柄等系統資源。
public abstract void write(int b) throws IOException; // 僅寫入低 8 位
public void write(byte[] b) throws IOException public void write(byte[] b, int off, int len) throws IOException
flush():將緩衝區數據推向下游(如操作系統內核緩衝),FileOutputStream 無緩衡,調用無效果。close():隱式調用 flush() 後釋放資源。注意:FileOutputStream.getFD().sync()才能強制數據落盤,普通flush()僅交給 OS。
new FileOutputStream(file, true) // true = 追加模式,false/無參 = 覆蓋模式
無寫權限拋 SecurityException;路徑指向目錄拋 FileNotFoundException。
文件必須存在且可讀,否則拋異常。
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");
裝飾任意流,提供 writeInt、writeDouble、writeUTF 等方法,按大端序寫入二進制。配合 BufferedOutputStream 使用性能最佳:
DataOutputStream out = new DataOutputStream(
new BufferedOutputStream(new FileOutputStream("data.dat")));
BufferedInputStream 額外支持 mark/reset。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);
}
public static byte[] readFileToByteArray(String path) throws IOException {
try (InputStream in = new FileInputStream(path);
ByteArrayOutputStream out = new ByteArrayOutputStream()) {
copy(in, out);
return out.toByteArray();
}
}
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 編程本質。
