天天看點

Java的Reader和Writer

Reader

Reader

是Java的IO庫提供的另一個輸入流接口。和

InputStream

的差別是,

InputStream

是一個位元組流,即以

byte

為機關讀取,而

Reader

是一個 字元 流,即以

char

為機關讀取:

InputStream Reader
位元組流,以byte為機關 字元流,以char為機關
讀取位元組(-1,0~255):int read() 讀取字元(-1,0~65535):int read()
讀到位元組數組:int read(byte[] b) 讀到字元數組:int read(char[] c)

java.io.Reader

是所有字元輸入流的超類,它最主要的方法是:

這個方法讀取字元流的下一個字元,并傳回字元表示的

int

,範圍是 0~65535。如果已讀到末尾,傳回 -1。

FileReader

FileReader

Reader

的一個子類,它可以打開檔案并擷取

Reader

。下面的代碼示範了如何完整地讀取一個

FileReader

的所有字元:

public void readFile() throws IOException {
    // 建立一個FileReader對象:
    Reader reader = new FileReader("src/readme.txt"); 	
    for (;;) {
        int n = reader.read(); 	// 反複調用read()方法,直到傳回-1
        if (n == -1) {
            break;
        }
        System.out.println((char)n); 	// 列印char
    }
    reader.close(); 	// 關閉流
}
           

如果我們讀取一個純

ASCII

編碼的文本檔案,上述代碼工作是沒有問題的。但如果檔案中包含中文,就會出現亂碼,因為

FileReader

預設的編碼與系統相關,例如,Windows系統的預設編碼可能是

GBK

,打開一個

UTF-8

編碼的文本檔案就會出現亂碼。

要避免亂碼問題,我們需要在建立

FileReader

時 指定編碼 :

InputStream

類似,

Reader

也是一種資源,需要保證出錯的時候也能正确關閉,是以我們需要用

try (resource)

來保證

Reader

在無論有沒有 IO錯誤 的時候都能夠正确地關閉:

try (Reader reader = new FileReader("src/readme.txt", StandardCharsets.UTF_8) {
    // TODO
}
           

Reader

還提供了一次性讀取若幹字元并填充到

char[]數組

的方法:

public int read(char[] c) throws IOException
           

它傳回實際讀入的字元個數,最大不超過

char[]

數組的長度。傳回 -1 表示流結束。

利用這個方法,我們可以先設定一個緩沖區,然後,每次盡可能地填充緩沖區:

public void readFile() throws IOException {
    try (Reader reader = new FileReader("src/readme.txt", StandardCharsets.UTF_8)) {
        char[] buffer = new char[1000];
        int n;
        while ((n = reader.read(buffer)) != -1) {
            System.out.println("read " + n + " chars.");
        }
    }
}
           

StringReader

StringReader

可以直接把

String

作為資料源:

try (Reader reader = new StringReader("Hello")) {
}
           

Writer

Reader

是帶編碼轉換器的

InputStream

,它把

byte

轉換為

char

,而

Writer

就是帶編碼轉換器的

OutputStream

,它把

char

轉換為

byte

并輸出。

Writer

OutputStream

的差別如下:

OutputStream Writer
位元組流,以byte為機關 字元流,以char為機關
寫入位元組(0~255):void write(int b) 寫入字元(0~65535):void write(int c)
寫入位元組數組:void write(byte[] b) 寫入字元數組:void write(char[] c)
無對應方法 寫入String:void write(String s)

Writer

是所有字元輸出流的超類,它提供的方法主要有:

  • 寫入一個字元(0~65535):

    void write(int c)

  • 寫入字元數組的所有字元:

    void write(char[] c)

  • 寫入String表示的所有字元:

    void write(String s)

FileWriter

FileWriter

就是向檔案中寫入字元流的

Writer

。它的使用方法和

FileReader

類似:

try (Writer writer = new FileWriter("readme.txt", StandardCharsets.UTF_8)) {
    writer.write('H'); 		// 寫入單個字元
    writer.write("Hello".toCharArray()); 	// 寫入char[]
    writer.write("Hello"); 	// 寫入String
}
           

StringWriter

StringWriter

也是一個基于記憶體的

Writer

。實際上,StringWriter 在内部維護了一個

StringBuffer

,并對外提供了

Writer

接口。

繼續閱讀