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

徹底掌握 Java IO 體系:從流分類到裝飾者模式實戰

     編輯:Java 程式設計入門

Java IO 體系龐雜,初學者易迷失在眾多類名中。本文以「流的導向」、「裝飾者模式增強」、「隨機訪問」三條主線,系統梳理核心類結構與實戰組合模式,助你建立清晰的 IO 知識地圖。

一、 兩大流體系:字節流與字符流

Java IO 按處理單位劃分為 字節流(Byte Stream) 與 字符流(Char Stream),分別對應 8-bit 字節與 16-bit Unicode 字符。

1.1 字節流核心類

方向節點流(直接操作目標)用途
輸入ByteArrayInputStream內存緩衝區作為輸入源
FileInputStream文件讀取
PipedInputStream線程間管道通信
SequenceInputStream合併多個輸入流
StringBufferInputStream (已棄用)字符串轉輸入流
輸出ByteArrayOutputStream寫入內存緩衝區
FileOutputStream文件寫入
PipedOutputStream線程間管道通信
SequenceOutputStream合併多個輸出流

1.2 字符流核心類(對應字節流)

字符流類名以 Reader/Writer 結尾,功能與字節流對應,差別在於讀寫單位為 char,內部自動處理編碼轉換。

  • CharArrayReader ↔ ByteArrayInputStream
  • StringReader ↔ StringBufferInputStream
  • FileReader ↔ FileInputStream
  • PipedReader ↔ PipedInputStream
  • CharArrayWriter ↔ ByteArrayOutputStream
  • StringWriter(無字節對應)
  • FileWriter ↔ FileOutputStream
  • PipedWriter ↔ PipedOutputStream

1.3 字節流 ⇄ 字符流 轉換橋樑

  • InputStreamReader:字節輸入流 → 字符輸入流(指定 Charset)
  • OutputStreamWriter:字節輸出流 → 字符輸出流(指定 Charset)

最佳實踐: 涉及文本文件讀寫,優先使用 FileReader/FileWriter 或顯式指定編碼的轉換流,避免平台默認編碼差異導致亂碼。

二、 裝飾者模式:為流動態添加職責

Java IO 大量使用 裝飾者模式,通過 FilterInputStream/FilterOutputStream 及其子類,在不修改原流類的前提下,動態組合功能:緩衝、格式化、基本類型讀寫、行號記錄等。

2.1 常用裝飾類速查表

功能字節流裝飾字符流裝飾
緩衝(提升效率)BufferedInputStreamBufferedReader
基本類型讀寫DataInputStream / DataOutputStream—(改用 BufferedReader.readLine)
行號記錄LineNumberInputStream (棄用)LineNumberReader
回退讀取PushbackInputStreamPushbackReader
格式化輸出PrintStreamPrintWriter

2.2 實戰組合範例

// 高效讀取文本文件(緩衝 + 字符流 + 指定編碼)
try (BufferedReader in = new BufferedReader(
        new InputStreamReader(new FileInputStream("data.txt"), StandardCharsets.UTF_8))) {
    String line;
    while ((line = in.readLine()) != null) { /* process */ }
}

// 高效寫入二進制數據(緩衝 + 基本類型)
try (DataOutputStream out = new DataOutputStream(
        new BufferedOutputStream(new FileOutputStream("data.bin")))) {
    out.writeDouble(3.14159);
    out.writeUTF("Hello World");
}

三、 RandomAccessFile:隨機訪問文件的利器

RandomAccessFile 獨立於流體系,同時實現 DataInput/DataOutput 接口,支持:

  • 模式:"r"(只讀)、"rw"(讀寫)、"rws"/"rwd"(同步寫入)
  • seek(long pos) 定位文件指針
  • getFilePointer() 獲取當前位置
  • length() 獲取文件長度

適用場景:大文件斷點續傳、稀疏文件處理、需要隨機修改固定長度記錄的數據文件。

四、 綜合實戰案例解析

以下代碼演示了六大典型 IO 操作場景:

import java.io.*;

public class IODemo {
    public static void main(String[] args) throws IOException {
        // 1. 緩衝按行讀取文件
        StringBuilder content = new StringBuilder();
        try (BufferedReader br = new BufferedReader(new FileReader("TestIO.java"))) {
            String line;
            while ((line = br.readLine()) != null) content.append(line).append("\n");
        }

        // 2. 從鍵盤讀取一行(標準輸入轉字符流再緩衝)
        try (BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in))) {
            System.out.println("輸入一行: " + stdin.readLine());
        }

        // 3. 從字符串讀取(StringReader)
        try (StringReader sr = new StringReader(content.toString())) {
            int c;
            while ((c = sr.read()) != -1) System.out.print((char) c);
        }

        // 4. 內存格式化輸出(ByteArray + DataInput)
        try (DataInputStream dis = new DataInputStream(
                new ByteArrayInputStream(content.toString().getBytes()))) {
            while (true) System.out.print((char) dis.readByte());
        } catch (EOFException ignored) { System.out.println("\nEnd of stream"); }

        // 5. 輸出到文件(緩衝 + 格式化 + 行號)
        try (BufferedReader br = new BufferedReader(new StringReader(content.toString()));
             PrintWriter pw = new PrintWriter(new BufferedWriter(new FileWriter("TestIO.out")))) {
            int lineNo = 1;
            String line;
            while ((line = br.readLine()) != null) pw.println(lineNo++ + ":" + line);
        }

        // 6. 數據存儲與恢復(DataOutput/Input + 緩衝)
        try (DataOutputStream dos = new DataOutputStream(
                new BufferedOutputStream(new FileOutputStream("Data.txt")))) {
            dos.writeDouble(Math.PI);
            dos.writeChars(" Thas was pi:writeChars ");
            dos.writeBytes("Thas was pi:writeByte ");
        }
        try (DataInputStream dis = new DataInputStream(
                new BufferedInputStream(new FileInputStream("Data.txt")));
             BufferedReader br = new BufferedReader(new InputStreamReader(dis))) {
            System.out.println(dis.readDouble());
            System.out.println(br.readLine());
            System.out.println(br.readLine());
        } catch (EOFException ignored) { System.out.println("End of stream"); }

        // 7. RandomAccessFile 隨機讀寫
        try (RandomAccessFile rf = new RandomAccessFile("rtest.dat", "rw")) {
            for (int i = 0; i < 10; i++) rf.writeDouble(i * 1.414);
        }
        try (RandomAccessFile rf = new RandomAccessFile("rtest.dat", "r")) {
            for (int i = 0; i < 10; i++) System.out.println("Value " + i + ":" + rf.readDouble());
        }
        try (RandomAccessFile rf = new RandomAccessFile("rtest.dat", "rw")) {
            rf.seek(5 * 8); // 定位第 6 個 double
            rf.writeDouble(47.0001);
        }
        try (RandomAccessFile rf = new RandomAccessFile("rtest.dat", "r")) {
            for (int i = 0; i < 10; i++) System.out.println("Value " + i + ":" + rf.readDouble());
        }
    }
}

五、 核心設計模式總結

  1. 裝飾者模式:FilterInputStream 及子類動態組合功能,避免繼承爆炸。
  2. 適配器模式:InputStreamReader/OutputStreamWriter 適配字節流與字符流接口差異。
  3. 工廠模式:Files.newBufferedReader() (NIO.2) 簡化流創建。

掌握 Java IO 的關鍵在於理解「流的導向決定處理單位,裝飾者決定功能組合」。實戰中優先使用 try-with-resources 確保資源釋放,文本處理首選字符流 + 顯式編碼,二進制處理首選字節流 + 緩衝,隨機訪問選 RandomAccessFile 或 NIO FileChannel。內化這套邏輯,IO 代碼將不再是「管道連接」的試錯遊戲,而是精準可控的工程藝術。

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