Java基礎-IO流對象之轉換流(InputStreamReader與OutoutStreamWriter)
作者:尹正傑
版權聲明:原創作品,謝絕轉載!否則將追究法律責任。
一.轉換流概述
我們之前介紹過FileWrite和FileReader兩個字符類,FileReader是用來讀取字符文件的便捷類。此類的構造方法假定默認字符編碼和默認字節緩沖區大小都是適當的。要自己指定這些值,可以先在 FileInputStream 上構造一個 InputStreamReader。 FileWriter是用來寫入字符文件的便捷類。此類的構造方法假定默認字符編碼和默認字節緩沖區大小都是可接受的。要自己指定這些值,可以先在 FileOutputStream 上構造一個 OutputStreamWriter。
那么InputStreamReader和OutputStreamWriter到底是上面東西呢?其實它們就是我們今天要介紹的轉換流。它是字節流到字符流的一種橋梁,可使用指定的字符集將要寫入流中的字符編碼成字節。操作的數據單位是:字符,換句話說,轉換流就是將對字節的操作轉換成對字符的操作。
二.OutputStreamWriter寫文本文件
查閱OutputStreamWriter的API介紹,OutputStreamWriter 是字符流通向字節流的橋梁:可使用指定的字符編碼表,將要寫入流中的字符編碼成字節。它的作用的就是,將字符串按照指定的編碼表轉成字節,在使用字節流將這些字節寫出去。
其實在OutputStreamWriter流中維護自己的緩沖區,當我們調用OutputStreamWriter對象的write方法時,會拿着字符到指定的碼表中進行查詢,把查到的字符編碼值轉成字節數存放到OutputStreamWriter緩沖區中。然后再調用刷新功能,或者關閉流,或者緩沖區存滿后會把緩沖區中的字節數據使用字節流寫到指定的文件中。
1 /* 2 @author :yinzhengjie 3 Blog:http://www.cnblogs.com/yinzhengjie/tag/Java%E5%9F%BA%E7%A1%80/ 4 EMAIL:y1053419035@qq.com 5 */ 6 7 package cn.org.yinzhengjie.note5; 8 9 import java.io.FileOutputStream; 10 import java.io.IOException; 11 import java.io.OutputStreamWriter; 12 13 public class OutputStreamDemo { 14 public static void main(String[] args) throws IOException { 15 writeGBK("yinzhengjie.gbk"); 16 writeUTF8("yinzhengjie.utf-8"); 17 } 18 19 //使用UTF-8編碼寫入文件 20 public static void writeUTF8(String fileName) throws IOException { 21 //創建字節輸出流,綁定文件 22 FileOutputStream fos = new FileOutputStream(fileName); 23 //創建轉換流對象,構造方法保證字節輸出流,並指定編碼表是UTF-8 24 OutputStreamWriter osw = new OutputStreamWriter(fos, "UTF-8"); 25 osw.write("尹正傑"); 26 osw.close(); 27 28 } 29 30 //使用GBK編碼寫入文件 31 public static void writeGBK(String fileName) throws IOException { 32 //創建字節輸出流,綁定數據文件 33 FileOutputStream fos = new FileOutputStream(fileName); 34 //創建轉換流對象,構造方法,綁定字節輸出流,使用GBK編碼表 35 OutputStreamWriter osw = new OutputStreamWriter(fos, "GBK"); 36 //轉換流寫數據 37 osw.write("尹正傑"); 38 //關閉osw轉換流后,就默認會關閉fos流。 39 osw.close(); 40 } 41 42 }
注意:OutputStreamWriter還有一個子類,即FileWriter,它不能指定字符編碼表,而是用系統默認的編碼表。
三.InputSteamReader讀取文本文件
查閱InputStreamReader的API介紹,InputStreamReader 是字節流通向字符流的橋梁:它使用指定的字符編碼表讀取字節並將其解碼為字符。它使用的字符集可以由名稱指定或顯式給定,或者可以接受平台默認的字符集。
注意:在讀取指定的編碼的文件時,一定要指定編碼格式,否則就會發生解碼錯誤,而發生亂碼現象。InputStreamReader也有一個子類,即FileReaderr,它不能指定字符編碼表,而是用系統默認的編碼表。
1 /* 2 @author :yinzhengjie 3 Blog:http://www.cnblogs.com/yinzhengjie/tag/Java%E5%9F%BA%E7%A1%80/ 4 EMAIL:y1053419035@qq.com 5 */ 6 7 package cn.org.yinzhengjie.note5; 8 9 import java.io.FileInputStream; 10 import java.io.FileNotFoundException; 11 import java.io.IOException; 12 import java.io.InputStreamReader; 13 14 public class InputStreamReaderDemo { 15 public static void main(String[] args) throws IOException { 16 readGBK("yinzhengjie.gbk"); 17 System.out.println("---------我是分割線------"); 18 readUTF("yinzhengjie.utf-8"); 19 20 } 21 //讀取UTF-8的文件 22 public static void readUTF(String fileName) throws IOException { 23 //創建字節輸出流,傳遞文本文件。 24 FileInputStream fis = new FileInputStream(fileName); 25 //創建轉換流對象,構造方法中,包裝字節輸入流,同時寫編碼表名 26 InputStreamReader isr = new InputStreamReader(fis,"UTF-8"); 27 char[] buf = new char[4096]; 28 int len ; 29 while((len = isr.read(buf)) != -1) { 30 System.out.println(new String(buf,0,len)); 31 } 32 //釋放資源 33 isr.close(); 34 35 } 36 37 38 //讀取GBK編碼文件 39 public static void readGBK(String fileName) throws IOException { 40 //創建輸入流,傳遞文本文件。 41 FileInputStream fis = new FileInputStream(fileName); 42 //創建轉換流對象,構造方法包裝字節輸出流 43 InputStreamReader isr = new InputStreamReader(fis,"GBK"); 44 char[] buf = new char[4096]; 45 int len ; 46 while(( len = isr.read(buf)) != -1 ) { 47 System.out.println(new String(buf,0,len)); 48 } 49 //釋放資源 50 isr.close(); 51 } 52 } 53 54 55 /* 56 以上代碼執行結果如下: 57 尹正傑 58 ---------我是分割線------ 59 尹正傑 60 */
四.轉換流子類父類的區別
OutputStreamWriter和InputStreamReader是字符和字節的橋梁:也可以稱之為字符轉換流。字符轉換流原理:字節流+編碼表。
FileWriter和FileReader:作為子類,僅作為操作字符文件的便捷類存在。當操作的字符文件,使用的是默認編碼表時可以不用父類,而直接用子類就完成操作了,簡化了代碼。
1 InputStreamReader isr = new InputStreamReader(new FileInputStream("yinzhengjie.gbk"));//默認字符集。
2 InputStreamReader isr = new InputStreamReader(new FileInputStream("yinzhengjie.gbk"),"GBK");//指定GBK字符集。
3 FileReader fr = new FileReader("yinzhengjie.gbk"); //這三句代碼的功能是一樣的,其中第三句最為便捷。
如果在Windows操作系統下,上面三行代碼的功能是一樣的,其中第三種讀取方式最為便捷。注意:一旦要指定其他編碼時,絕對不能用子類,必須使用字符轉換流。什么時候用子類呢?條件一:操作的是文件;條件二:使用默認編碼;