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

Java I/O 流對象選型決策樹:從源頭到目的地的完整選型指南

     編輯:Java 相關知識

前言

Java I/O 體系龐大(40+ 類),初學者常陷入「不知選哪個流」的困境。本文提供**三步決策法**、**裝飾者模式組合表**、**實戰場景對照表**,讓流選型變得機械化、標準化。

一、三步決策法(核心心法)

步驟 1:確定資料流向

  • 輸入:資料從外部進入程式 → **InputStream / Reader**
  • 輸出:資料從程式寫出外部 → **OutputStream / Writer**

步驟 2:確定資料型別

  • 純文字**:字元、字串、JSON、XML、CSV → **Reader / Writer**(字元流,16-bit char)
  • 二進位**:圖片、視訊、音訊、序列化物件、壓縮檔 → **InputStream / OutputStream**(位元組流,8-bit byte)

步驟 3:確定源/目的裝置

二、裝飾者模式組合速查表(效能與功能增強)

2.1 位元組流裝飾鏈


// 基礎節點流
InputStream in = new FileInputStream("data.bin");

// 第一層:緩衝(必加,提升效能 10-100 倍)
BufferedInputStream bin = new BufferedInputStream(in);

// 第二層:資料型別轉換(可選)
DataInputStream din = new DataInputStream(bin); // 讀基本型別
ObjectInputStream oin = new ObjectInputStream(bin); // 反序列化物件
GZIPInputStream gin = new GZIPInputStream(bin); // 解壓縮

// 一行式組合(實戰推薦)
try (ObjectInputStream ois = new ObjectInputStream(
         new BufferedInputStream(new FileInputStream("user.dat")))) {
    User user = (User) ois.readObject();
}

2.2 字元流裝飾鏈


// 基礎節點流
Reader reader = new FileReader("data.txt", StandardCharsets.UTF_8); // Java 11+

// 第一層:緩衝(必加,支援 readLine())
BufferedReader br = new BufferedReader(reader);

// 第二層:掃描/解析(可選)
Scanner scanner = new Scanner(br); // 正則分詞
LineNumberReader lnr = new LineNumberReader(br); // 行號追蹤

// 一行式組合
try (BufferedReader br = new BufferedReader(
         new FileReader("config.txt", StandardCharsets.UTF_8))) {
    String line;
    while ((line = br.readLine()) != null) { /* 處理 */ }
}

2.3 跨界轉換:位元組 ↔ 字元


// 位元組流 → 字元流(指定編碼,解決中文亂碼)
InputStreamReader isr = new InputStreamReader(new FileInputStream("data.txt"), "UTF-8");
BufferedReader br = new BufferedReader(isr);

// 字元流 → 位元組流
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("out.txt"), "UTF-8");
BufferedWriter bw = new BufferedWriter(osw);

// Java 11+ 簡化
Reader reader = new FileReader("data.txt", StandardCharsets.UTF_8);
Writer writer = new FileWriter("out.txt", StandardCharsets.UTF_8);

三、實戰場景標準組合

裝置輸入流輸出流
檔案FileInputStreamFileOutputStream
檔案(文字)FileReaderFileWriter
記憶體陣列ByteArrayInputStreamByteArrayOutputStream
記憶體陣列(文字)CharArrayReaderCharArrayWriter
字串StringReaderStringWriter
網路 Socketsocket.getInputStream()socket.getOutputStream()
標準輸入/輸出System.inSystem.out / System.err
管道(執行緒間)PipedInputStreamPipedOutputStream
場景標準組合關鍵點
複製二進位檔案FileInputStream → BufferedInputStream → BufferedOutputStream → FileOutputStream緩衝區大小 8KB-64KB
讀取文字檔案(逐行)FileReader → BufferedReader → readLine()指定編碼 UTF-8
寫入文字檔案FileWriter → BufferedWriter → write()/newLine()flush() 確保落盤
物件序列化/反序列化ObjectOutputStream/ObjectInputStream + Buffered實作 Serializable、serialVersionUID
資料型別讀寫DataOutputStream/DataInputStream + Buffered順序一致、UTF-8 字串
壓縮/解壓縮GZIPOutputStream/GZIPInputStream + Buffered大檔案分塊處理
網路通訊Socket.getInputStream()/getOutputStream() + Buffered設定 SO_TIMEOUT、KeepAlive
控制台互動System.in → InputStreamReader → BufferedReader / ScannerScanner 適合分詞,BufferedReader 適合逐行
記憶體高速緩衝ByteArrayOutputStream / ByteArrayInputStream避免磁碟 IO、單元測試 Mock
隨機存取檔案RandomAccessFile ("rw")seek() 定位、支援斷點續傳

四、NIO.2 現代替代方案(Java 7+)

4.1 Files 工具類(靜態方法,簡潔)


// 讀取全部行
List lines = Files.readAllLines(Paths.get("data.txt"), StandardCharsets.UTF_8);

// 串流處理大檔案
try (Stream lines = Files.lines(Paths.get("big.log"), StandardCharsets.UTF_8)) {
    lines.filter(l -> l.contains("ERROR")).forEach(System.out::println);
}

// 複製/移動/刪除
Files.copy(src, dest, StandardCopyOption.REPLACE_EXISTING);
Files.move(src, dest, StandardCopyOption.ATOMIC_MOVE);
Files.deleteIfExists(path);

4.2 Channel 與 Buffer(高效能、非阻塞)


try (FileChannel in = FileChannel.open(Paths.get("src"), StandardOpenOption.READ);
     FileChannel out = FileChannel.open(Paths.get("dest"), StandardOpenOption.WRITE, StandardOpenOption.CREATE)) {
    
    // 直接通道傳輸(零拷貝,OS 級優化)
    in.transferTo(0, in.size(), out);
    
    // 或 MappedByteBuffer(記憶體映射,超大檔案)
    MappedByteBuffer buffer = in.map(FileChannel.MapMode.READ_ONLY, 0, in.size());
    out.write(buffer);
}

五、避坑指南

  1. 忘記關閉流:`try-with-resources` 強制釋放資源
  2. 未指定編碼**:`new FileReader(file)` 使用平台預設編碼,**必須** `StandardCharsets.UTF_8`
  3. 緩衝區未刷新**:`BufferedWriter`/`PrintWriter` 需 `flush()` 或 `close()` 觸發
  4. 位元組流讀文字**:中文亂碼根因,需 `InputStreamReader` 指定編碼
  5. 裝飾鏈順序錯誤**:緩衝**最貼近節點流**,轉換/壓縮/序列化在外層
  6. 大檔案一次性讀入記憶體**:OOM 風險,必須串流/分塊處理

總結

**三步決策法(流向 → 型別 → 裝置)+ 裝飾者組合(緩衝必加 + 功能按需)+ NIO.2 現代 API** 構成完整選型體系。將 40+ 流類歸納為「節點流(源/目的)」與「處理流(裝飾者)」兩大類,掌握標準組合模式,I/O 選型不再是難題。

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