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

Java IO 進階避坑指南:流選擇策略、非順序讀取與中文編碼處理

     編輯:Java 相關知識

面對龐大 IO 體系,如何精準選型?

Java IO 超過 50 個類,初學者常陷入「不知從何下手」。掌握三步選型法,輕鬆鎖定目標類:

第一步:按數據源選實體流(必選,且只能選一個)

數據源位元組流字符流
檔案FileInputStream / FileOutputStreamFileReader / FileWriter
記憶體陣列ByteArrayInputStream / OutputStreamCharArrayReader / Writer
網路連線Socket.getInputStream() / OutputStream()搭配橋接流轉換
控制台System.in / System.out搭配橋接流轉換

第二步:按方向選流向

  • 讀 → InputStream / Reader
  • 寫 → OutputStream / Writer

第三步:優先字符流,除非處理二進制

文字、配置、XML、JSON → 字符流(Reader/Writer)效率更高、編碼處理內建。
圖片、聲音、視頻、序列化物件 → 位元組流(InputStream/OutputStream)。

裝飾流選擇:按需疊加(可選多個,順序不限)

進階技巧:非順序讀取與重複讀取

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)) {
    
    // 讀取邏輯
} // 自動按逆序關閉,即使發生異常也保證關閉

總結

  1. 三步選型法:數據源 → 方向 → 字符/位元組優先級。
  2. 裝飾流按需疊加,掌握核心 4 類功能:緩衝、數據類型、格式化、編碼轉換。
  3. mark/reset 解決重複讀取,skip 解決跳過讀取。
  4. 中文編碼:全鏈路統一 Charset,推薦 UTF-8,善用 writeUTF/readUTF。
  5. 資源管理:強制使用 try-with-resources。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved
需求裝飾流核心方法
提高讀寫效率(緩衝)BufferedInputStream/OutputStream
BufferedReader/Writer
readLine()、buffer size 調整
基本類型/物件直接讀寫DataInputStream/OutputStream
ObjectInputStream/OutputStream
readInt()/writeInt()、readObject()/writeObject()
格式化輸出PrintStream/PrintWriterprintf()、println()
編碼轉換InputStreamReader/OutputStreamWriter指定 Charset