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

Java I/O 字符輸入流 Reader 體系全解析

     編輯:Java 程式設計入門

Java 字符輸入流 Reader 體系架構

在 Java I/O 體系中,字符輸入流 Reader 扮演著核心角色。本文將系統梳理 Reader 的繼承體系與核心實現類,幫助開發者快速建立完整的知識框架。以下是 Reader 的主要子類分類:

Reader 類結構圖

  • 抽象基類:Reader —— 所有字符輸入流的根節點
  • 字節轉字符橋樑:InputStreamReader —— 將字節流解碼為字符流
  • 文件讀取:FileReader —— 直接讀取本地字符文件
  • 內存數組讀取:CharArrayReader —— 以字符數組為數據源
  • 線程間通信:PipedReader —— 配合 PipedWriter 實現同一 JVM 內線程通信
  • 緩衝增強:BufferedReader —— 提供行讀取等高級功能
  • 過濾框架:FilterReader —— 自定義過濾邏輯的基類
  • 字符串讀取:StringReader —— 將字符串作為輸入源
  • 特殊解析:PushbackReader(支持回退)、LineNumberReader(行號追蹤)

InputStreamReader:字節與字符的轉換樞紐

InputStreamReader 是連接字節流與字符流的關鍵橋樑。其每個構造方法均接收一個 InputStream 參數,底層通過 StreamDecoder 實現解碼邏輯(包括構造時的 StreamDecoder.forInputStreamReader 與讀取時的 StreamDecoder.read)。

InputStreamReader 源碼結構

提示:有興趣深入了解解碼機制的讀者可自行研讀 StreamDecoder 源碼。

代碼示例:標準輸入讀取

package io;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Reader;

public class IOTest {
    public static void main(String[] args) throws IOException {
        // 將標準字節輸入流包裝為字符輸入流
        Reader reader = new InputStreamReader(System.in);
        // 讀取單個字符並輸出
        System.out.println((char) reader.read());
        reader.close();
    }
}
// 輸入範例:鍵盤輸入 0 → 輸出 0

FileReader:本地文件讀取的便捷入口

FileReader 繼承自 InputStreamReader,專門用於讀取本地字符文件。其構造方法內部會先根據參數創建 FileInputStream,再調用父類構造方法完成字節到字符的轉換。

FileReader 構造方法

代碼示例:文件讀取

package io;
import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;

public class IOTest {
    public static void main(String[] args) throws IOException {
        Reader reader = new FileReader("C:\\test.txt");
        System.out.println((char) reader.read());
        reader.close();
    }
}

CharArrayReader:內存字符數組的流式訪問

CharArrayReader 允許直接將字符數組作為輸入源。值得注意的是,它持有對外部數組的引用,因此數組內容的變更會即時反映到流的讀取結果中。

CharArrayReader 構造方法

代碼示例:數組變更的即時性

package io;
import java.io.CharArrayReader;
import java.io.IOException;
import java.io.Reader;

public class IOTest {
    public static void main(String[] args) throws IOException {
        char[] charArr = {'a', 'b', 'c'};
        Reader reader = new CharArrayReader(charArr);
        // 修改原數組
        charArr[0] = 'e';
        // 讀取到的是修改後的 'e'
        System.out.println((char) reader.read());
        reader.close();
    }
}

PipedReader:線程間的字符管道

PipedReader 需與 PipedWriter 配合使用,實現同一 JVM 內兩個線程的字符數據傳輸。讀寫操作均為阻塞式,典型場景為生產者-消費者模型。

代碼示例:線程通信

package io;
import java.io.IOException;
import java.io.PipedReader;
import java.io.PipedWriter;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class IOTest {
    public static void main(String[] args) throws IOException {
        final PipedWriter pw = new PipedWriter();
        final PipedReader pr = new PipedReader(pw);
        ExecutorService es = Executors.newFixedThreadPool(2);
        
        es.execute(() -> {
            try { pw.write("hello~"); } 
            catch (IOException e) { e.printStackTrace(); }
        });
        
        es.execute(() -> {
            char[] cbuffer = new char[6];
            try { pr.read(cbuffer, 0, 6); } 
            catch (IOException e) { e.printStackTrace(); }
            System.out.println(cbuffer);
        });
    }
}

BufferedReader:緩衝與行讀取的雙重優勢

採用裝飾器模式設計,BufferedReader 為被裝飾流提供字符緩衝區,避免頻繁訪問底層介質,並新增 readLine() 等實用方法。參考:裝飾器模式詳解

代碼示例:帶緩衝的文件逐行讀取

package io;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;

public class IOTest {
    public static void main(String[] args) throws IOException {
        // 指定 10KB 緩衝區
        BufferedReader reader = new BufferedReader(
            new FileReader("C:\\test.txt"), 10 * 1024);
        System.out.println(reader.readLine());
        System.out.println(reader.readLine());
        System.out.println(reader.readLine());
        reader.close();
    }
}

LineNumberReader:行號感知的讀取器

繼承自 BufferedReader,除保留所有功能外,新增行號追蹤能力。需注意 setLineNumber() 僅修改內部計數器,不會導致流跳轉。

代碼示例:行號獲取

package io;
import java.io.FileReader;
import java.io.IOException;
import java.io.LineNumberReader;

public class IOTest {
    public static void main(String[] args) throws IOException {
        LineNumberReader reader = new LineNumberReader(
            new FileReader("C:\\test.txt"), 10 * 1024);
        System.out.println(reader.getLineNumber()); // 0
        System.out.println(reader.readLine());
        System.out.println(reader.getLineNumber()); // 1
        System.out.println(reader.readLine());
        reader.close();
    }
}

FilterReader:自定義過濾的基石

抽象類 FilterReader 簡單覆寫了 Reader 的所有方法,作為實現自定義過濾邏輯的基類。雖然功能看似單薄,但為擴展提供了標準契約。

PushbackReader:支持回退的靈活讀取

同樣基於裝飾器模式,PushbackReader 允許通過 unread() 將已讀字符推回緩衝區,下次讀取優先從緩衝區獲取。常用於需要「回頭看」的解析場景(如詞法分析)。

代碼示例:字符回退

package io;
import java.io.FileReader;
import java.io.IOException;
import java.io.PushbackReader;

public class IOTest {
    public static void main(String[] args) throws IOException {
        PushbackReader reader = new PushbackReader(
            new FileReader("C:\\test.txt"), 1024);
        char a = (char) reader.read();
        System.out.println(a);
        reader.unread(a); // 推回緩衝區
        System.out.println((char) reader.read()); // 再次讀取同一字符
        System.out.println((char) reader.read()); // 讀取下一字符
        reader.close();
    }
}

StringReader:字符串輸入流化

最輕量的實現,直接將字符串轉為字符輸入流,適合單元測試或簡單解析場景。

代碼示例

package io;
import java.io.IOException;
import java.io.StringReader;

public class IOTest {
    public static void main(String[] args) throws IOException {
        StringReader reader = new StringReader("hello~");
        char[] cbuf = new char[6];
        reader.read(cbuf, 0, 6);
        System.out.println(cbuf);
        reader.close();
    }
}
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved