轉換流(將位元組流轉換為字元流)
1、將位元組流轉換為字元流
(1)名稱是前面四種抽象類的組合
(2)功能都是將位元組流轉換成字元流,但是沒有將字元流轉換成位元組流的類,因為,已經獲得了字元流,根本沒有必要轉換成位元組流
(3)InputStreamReader是將InputStream中的位元組轉換成字元
OutputStreamWriter是將OutputStream中的位元組轉換成字元
(4)InputStreamReader和OutputStreamWriter兩個類可以指定編碼集合
(5)為什麼要指定編碼集合呢?
因為將位元組轉換成字元,讀到程式中的時候,java程式在記憶體中的字元都是Unicode編碼的但是從檔案中讀取的內容有自己的編碼格式,可能是jbk編碼,可能是ISO8859_1編碼,還有可能是ASCILL編碼,編碼不同,所以要根據已有編碼轉換成Unicode編碼,因此可以指定這些字元到底是什麼編碼格式的,但是如果指定編碼格式錯誤的話,會出現亂碼問題。
(6)怎麼會出現亂碼問題呢?
如果要將自己的編碼轉換成Unicode編碼字元的話,要先確定原始字元到底是什麼型別的編碼,如果指定原始字元格式錯誤的話,會出現亂碼問題。
2、例項1:TestTransform
—對TestFileInputStream的修改,可以讀取文中字元(TestTileInputStream.java原始碼檔案中有字元、中文、英文,但是是因為按照位元組來讀的,讀出來之後,很多中文都是亂碼的,我們知道可以通過FileReader來讀,同時也可以使用InputStreamReader來讀)
import java.io.*; /*對TestFileInputStream的修改,可以讀取文中字元*/ public class TestTransform { public static void main(String[] args) { int b=0; InputStreamReader isr=null; try { isr=new InputStreamReader(new FileInputStream("TestTileInputStream.java")); //通過InputStreamReader讀取FileInputStream中讀取的TestTileInputStream.java中的字元 long num=0; while((b=isr.read())!=-1) { System.out.print((char)b); num++; } System.out.println("共讀取了"+num+"個字元"); } catch(FileNotFoundException e) { System.out.println("找不到指定檔案"); } catch(IOException e1) { System.out.println("檔案讀取錯誤"); } finally { try { isr.close(); } catch(IOException e) { e.printStackTrace(); } } System.exit(-1); } }
最終正確地讀取了805個字元,與位元組數859不同,805個字元的位元組數更多
2、例項2:TestTransform
功能:分別以中文Windows預設的GBK和ISO8859_1編碼形式往檔案中寫入字串
import java.io.*; /*功能:分別以中文Windows預設的GBK和ISO8859_1編碼形式往檔案中寫入字串*/ public class TestTransFormEncoding { public static void main(String[] args) { try { OutputStreamWriter osw=new OutputStreamWriter(new FileOutputStream("transform1.txt")); //通過FileOutputStream檔案輸出流,往transform1.txt中寫資料 osw.write("計算機學院"); osw.write("SUN Java"); System.out.println(osw.getEncoding());//寫入的時候沒有指定編碼格式,那麼就採用中文Window預設編碼GBK osw.close(); //FileOutputStream構造方法第二個引數的含義,是否追加 osw=new OutputStreamWriter(new FileOutputStream("transform1.txt",true),"ISO8859_1"); /*這裡用FileOutputStream的過載方法,形參加了個true * 這裡本來預設是false,每次寫的時候,會覆蓋原來檔案的內容 * 但是加了true,意思是保留原有檔案內容,並且在原有檔案的尾部追加新的內容 * 編碼格式改成IS08859_1,指的是英文字元,沒有中文字串 * lantin-1 * */ osw.write("山東科技大學");//上面指定的編碼格式中,沒有文字字串 osw.write("C#"); System.out.println(osw.getEncoding()); osw.close(); } catch(IOException e) { e.printStackTrace(); } } }
第一次寫的時候沒有問題,第二次寫的時候C#沒有問題,但是“計算機學院”出現了問題,因為ISO8859_1格式中無法解碼中文
3、例項3:KeyboardInput
功能:實現鍵盤輸入功能,類似於現在的Scanner
import java.io.*;
public class KeyboardInput
{
public static void main(String[] args)
{
String s;
InputStreamReader isr=new InputStreamReader(System.in);
/*
* 本來應該套一個InputStream,但是套了System.in
* 所以System.in也是InputStream型別的
* 所以可以傳給InputStreamReader
* InputStreamReader套接了控制檯鍵盤輸入
* System.in讀入的是位元組,InputStreamReader轉換成了字元
* InputStreamReader只能一個字元一個字元地讀,比較麻煩,所以又套接了一個BufferedReader
* */
BufferedReader br=new BufferedReader(isr);//BufferedReader的特點,能一次讀取一行
System.out.println("Unix:Type ctrl-d or cril-c to exit."+"\nWindows:Type ctrl-z to exit");
try
{
//用Ctrl+z來結束
while((s=br.readLine())!=null)
{
System.out.println("Read: "+s);//輸入一行,列印一行
}
}
catch(IOException e)
{
e.printStackTrace();
}
finally
{
try
{
br.close();
}
catch(IOException e)
{
e.printStackTrace();
}
}
}
}
處理流怎麼工作的呢?
最終列印結果