| 需求 | 裝飾流 | 核心方法 |
| 提高讀寫效率(緩衝) | BufferedInputStream/OutputStream BufferedReader/Writer | readLine()、buffer size 調整 |
| 基本類型/物件直接讀寫 | DataInputStream/OutputStream ObjectInputStream/OutputStream | readInt()/writeInt()、readObject()/writeObject() |
| 格式化輸出 | PrintStream/PrintWriter | printf()、println() |
| 編碼轉換 | InputStreamReader/OutputStreamWriter | 指定 Charset |
進階技巧:非順序讀取與重複讀取
1. skip(long n) — 跳過不想要的資料
int skipped = fis.skip(100); // 從當前位置向後跳 100 bytes
// 實際跳過數量可能小於請求值,需檢查返回值
適用:固定格式檔案跳過頭部、索引式存取。
2. mark()/reset() — 書籤機制實現重複讀取
並非所有流支援,必須先檢查 markSupported()。
InputStream in = System.in;
if (in.markSupported()) {
in.mark(100); // 標記當前位置,允許往後最多讀 100 bytes 後仍可回退
byte[] buf = new byte[100];
int len = in.read(buf); // 第一次讀取
process(buf, len);
in.reset(); // 回到 mark 位置
len = in.read(buf); // 第二次讀取相同資料
process(buf, len);
}
內部原理:mark 後資料暫存於內部緩衝區,超過 readlimit 會失效。
中文亂碼終極解決方案
鐵律:字符串 → byte[] 使用的 Charset,必須與 byte[] → 字符串 使用的 Charset 完全一致。
錯誤示範
// 寫入用 UTF-8,讀取用 GBK → 亂碼
writer.write("中文".getBytes("UTF-8"));
String s = new String(bytes, "GBK");
正確姿勢
// 方式一:手動指定統一編碼
String charset = "UTF-8";
byte[] data = "中文".getBytes(charset);
// 寫入...
String restored = new String(bytes, charset);
// 方式二:用 DataOutputStream/InputStream 自動處理 UTF-8
dos.writeUTF("中文"); // 內部寫入長度 + UTF-8 bytes
String s = dis.readUTF(); // 自動解碼
檔案讀寫最佳實踐
// 寫入:明確指定編碼
try (Writer w = new OutputStreamWriter(new FileOutputStream("data.txt"), StandardCharsets.UTF_8)) {
w.write("中文內容");
}
// 讀取:明確指定編碼
try (Reader r = new InputStreamReader(new FileInputStream("data.txt"), StandardCharsets.UTF_8)) {
char[] buf = new char[1024];
int len = r.read(buf);
System.out.println(new String(buf, 0, len));
}
資源關閉鐵律:try-with-resources (Java 7+)
try (FileInputStream fis = new FileInputStream("a.txt");
BufferedInputStream bis = new BufferedInputStream(fis);
DataInputStream dis = new DataInputStream(bis)) {
// 讀取邏輯
} // 自動按逆序關閉,即使發生異常也保證關閉
總結
- 三步選型法:數據源 → 方向 → 字符/位元組優先級。
- 裝飾流按需疊加,掌握核心 4 類功能:緩衝、數據類型、格式化、編碼轉換。
- mark/reset 解決重複讀取,skip 解決跳過讀取。
- 中文編碼:全鏈路統一 Charset,推薦 UTF-8,善用
writeUTF/readUTF。
- 資源管理:強制使用 try-with-resources。
- 上一篇文章: Java 多線程核心基礎:進程與線程、優勢、生命週期全景圖
- 下一篇文章: Java IO 緩衝流與橋接流實戰:BufferedReader/Writer 高效讀寫控制台
Copyright ©
程式碼之家 All Rights Reserved