字節流與字符流之間的區別卻可以聯系起來,這就是表中的兩個類InputStreamReader和OutputStreamWriter。InputStreamReader負責把字節輸入流轉換為字符輸入流,OutputStreamWriter負責把輸出字節流轉換為輸出字符流。下面來看看如何進行轉換。
1.字節輸入流轉換為字符輸入流
InputStreamReader是字節流通向字符流的橋梁,它使用指定的charset讀取字節并將其解碼為字符。它擁有一個InputStream類型的變量,并繼承了Reader,使用了對象的適配器模式,如圖12-9所示。
根據InputStream的實例創建InputStreamReader的方法有4種:
- InputStreamReader(InputStream in);
- //根據默認字符集創建
- InputStreamReader(InputStream in, Charset cs);
- //使用給定字符集創建
- InputStreamReader(InputStream in, CharsetDecoder dec);
- //使用給定字符集解碼器創建
- InputStreamReader(InputStream in, String charsetName);
- //使用指定字符集創建
后面的3個構造函數都指定了一個字符集,最后一個是最簡單的,可以直接指定字符集的名稱來創建,例如GB2312等。
每次調用InputStreamReader中的一個read()方法都會導致從底層輸入流讀取一個或多個字節。要啟用從字節到字符的有效轉換,可以提前從底層流讀取更多的字節,使其超過滿足當前讀取操作所需的字節。共有3個可用的read()方法:
- int read();
- //讀取單個字符
- int read(char[] cbuf, int offset, int length);
- //將字符讀入數組中的某一部分
- boolean ready();
- //判斷此流是否已經準備好用于讀取
InputStreamReader繼承自Reader,因此該類的實例可以被各種輸入字符流包裝。為了達到最高效率,可以考慮在BufferedReader內包裝InputStreamReader。例如程序12-20所示,我們首先創建了一個FileInputStream類的實例,然后轉換為InputStreamReader對象is,最后使用BufferedReader進行包裝。這樣就可以將字節流轉換為帶緩沖功能的字符流。
程序12-20 TestInputStreamReader.java
- public class TestInputStreamReader {
- public static void main(String[] args) {
- try {
- // 創建輸入流
- FileInputStream fis = new FileInputStream("D:/demo/test.txt");
- InputStreamReader is = new InputStreamReader(fis);
- BufferedReader bis = new BufferedReader(is);
-
- // 從輸入流讀取數據
- while (bis.ready()) {
- int c = bis.read();
- System.out.print((char)c);
- }
-
- // 關閉輸入流
- bis.close();
- is.close();
- fis.close();
- } catch (IOException e) {
- }
- }
- }
2.字節輸出流轉換為字符輸出流
OutputStreamWriter是字符流通向字節流的橋梁,可使用指定的charset將要寫入流中的字符編碼成字節。因此,它擁有一個OutputStream類型的變量,并繼承了Writer,使用了對象的適配器模式,如圖12-10所示。
根據OutputStream的實例創建OutputStreamWriter的方法有4種:
- OutputStreamReader(OutputStream out);
- //根據默認字符集創建
- OutputStreamReader(OutputStream out, Charset cs);
- //使用給定字符集創建
- OutputStreamReader(OutputStream out, CharsetDecoder dec);
- //使用給定字符集解碼器創建
- OutputStreamReader(OutputStream out, Stroutg charsetName);
- //使用指定字符集創建
后面的3個構造函數都制定了一個字符集,最后一個是最簡單的,可以直接指定字符集的名稱來創建,例如GB2312等。
每次調用write()方法都會導致在給定字符(或字符集)上調用編碼轉換器。在寫入底層輸出流之前,得到的這些字節將在緩沖區中累積。可以指定此緩沖區的大小,不過,默認的緩沖區對多數用途來說已足夠大。注意,傳遞給write()方法的字符沒有緩沖。共有3個可用的write()方法:
- void write(char[] cbuf, int off, int len);//寫入字符數組的某一部分
- void write(int c);//寫入單個字符
- void write(String str, int off, int len);//寫入字符串的某一部分
OutputStreamWriter繼承自Writer,因此該類的實例可以被各種輸出字符流包裝。為了達到最高效率,可以考慮在BufferedWriter內包裝OutputStreamWriter。例如程序12-21所示,我們首先創建了一個FileOutputStream類的實例,然后轉換為OutputStreamReader對象os,最后使用BufferedWriter進行包裝。這樣就可以將字節流轉換為帶緩沖功能的字符流。
程序12-21 TestOutputStreamWriter.java
- public class TestOutputStreamWriter {
- public static void main(String[] args) {
- try {
- // 創建輸出流
- FileOutputStream fos = new FileOutputStream("D:/demo/test.txt");
- OutputStreamWriter os = new OutputStreamWriter(fos);
- BufferedWriter bos = new BufferedWriter(os);
-
- // 寫入數組數據
- char[] buf = new char[3];
- buf[0] = 'a';
- buf[1] = 'b';
- buf[2] = '中';
- bos.write(buf);
-
- // 關閉輸出流
- bos.close();
- os.close();
- fos.close();
- } catch (IOException e) {
- }
- }
- }