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

Java IO 體系全景圖:節點流與處理流、常用流類別與實戰技巧

     編輯:Java 相關知識

核心分類:節點流 vs 處理流

類型定義特徵典型代表
節點流直接連接資料源/目的地(檔案、記憶體、網路)資料的實際讀寫者FileInputStream, ByteArrayInputStream
處理流包裝現有流,提供額外功能(緩衝、轉換、序列化)建構子需傳入另一個流,形成流鏈BufferedReader, InputStreamReader

關鍵原則:關閉處理流會自動關閉被包裝的節點流;流可多層包裝形成鏈(如 new BufferedReader(new InputStreamReader(new FileInputStream(file))))。

節點流全家族

分類位元組流 (InputStream/OutputStream)字元流 (Reader/Writer)資料源
檔案FileInputStream / FileOutputStreamFileReader / FileWriter磁碟檔案
陣列ByteArrayInputStream / ByteArrayOutputStreamCharArrayReader / CharArrayWriter記憶體陣列
字串無StringReader / StringWriter字串緩衝區
管道PipedInputStream / PipedOutputStreamPipedReader / PipedWriter執行緒間通訊

處理流核心成員

1. 緩衝流 —— 效能加速器

// 位元組緩衝
BufferedInputStream bis = new BufferedInputStream(new FileInputStream("in.dat"));
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("out.dat"));

// 字元緩衝(支援 readLine())
BufferedReader br = new BufferedReader(new FileReader("text.txt"));
BufferedWriter bw = new BufferedWriter(new FileWriter("out.txt"));

核心優勢:減少系統呼叫次數,預設 8KB 緩衝區可調整。注意:寫入端需手動 flush() 強制輸出。

2. 轉換流 —— 位元組與字元橋樑


// 位元組 → 字元(指定編碼,避免平台預設編碼差異)
InputStreamReader isr = new InputStreamReader(new FileInputStream("utf8.txt"), "UTF-8");
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("out.txt"), "UTF-8");

解決 FileReader/FileWriter 硬編碼平台預設編碼的痛點。

3. 資料流 —— 基礎型別直接讀寫

DataOutputStream dos = new DataOutputStream(new FileOutputStream("data.bin"));
dos.writeLong(12345L);      // 固定 8 位元組
dos.writeInt(100);          // 固定 4 位元組
dos.writeUTF("中文");       // UTF-8 編碼 + 長度前綴

DataInputStream dis = new DataInputStream(new FileInputStream("data.bin"));
long v1 = dis.readLong();   // 必須與寫入順序、型別完全一致
int v2 = dis.readInt();
String v3 = dis.readUTF();

優勢:比「轉字串再轉位元組」節省空間、速度更快。風險:讀取順序/型別不匹配會導致資料錯位。

4. 物件流 —— 序列化利器

// 序列化
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("obj.dat"));
oos.writeObject(userList); // 需實作 Serializable

// 反序列化
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("obj.dat"));
List list = (List) ois.readObject();
關鍵字/介面作用
transient標記欄位不序列化(如密碼、暫存欄位)
Serializable標記介面,JVM 檢查 instanceof Serializable
serialVersionUID版本控制,避免類變更導致反序列化失敗
Externalizable手動控制序列化細節(writeExternal/readExternal)

5. 列印流 —— 不拋異常的友善輸出

PrintStream ps = new PrintStream(new FileOutputStream("log.txt"));
System.setOut(ps); // 重導向標準輸出
System.out.println("此行寫入檔案,不拋 IOException");

JSP/Servlet 大量使用 PrintWriter(response.getWriter()),設計初衷:Web 輸出不應因 IO 異常中斷請求處理。

中文亂碼根因與解決

根因:Java 內部用 UTF-16 (char 2 位元組),中文佔 2 位元組。位元組流單讀 1 位元組會截斷字元。
解決:堅持使用字元流 (Reader/Writer) 處理文本,或指定編碼的轉換流。

實戰最佳實踐

Try-with-resources(JDK 7+ 強制推薦)

try (BufferedReader br = new BufferedReader(new InputStreamReader(
        new FileInputStream("data.txt"), "UTF-8"))) {
    String line;
    while ((line = br.readLine()) != null) {
        process(line);
    }
} // 自動關閉,無需 finally

大檔案複製模板

public void copyLargeFile(File src, File dest) throws IOException {
    try (FileInputStream fis = new FileInputStream(src);
         FileOutputStream fos = new FileOutputStream(dest);
         FileChannel in = fis.getChannel();
         FileChannel out = fos.getChannel()) {
        // NIO 零拷貝,效能最優
        in.transferTo(0, in.size(), out);
    }
}

總結

Java IO 設計精妙地運用裝飾者模式:節點流負責「連接」,處理流負責「增強」。掌握「位元組流處理二進位、字元流處理文本、轉換流橋接兩者、緩衝流提升效能、物件流實現持久化」五大核心場景,即可駕馭絕大多數 IO 需求。現代專案更推薦 NIO.2 (Files, Path, FileChannel) 簡化程式碼並發揮零拷貝優勢。

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