1. 程式人生 > >轉換流(將位元組流轉換為字元流)

轉換流(將位元組流轉換為字元流)

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();
			}
		}
	}
}

 

處理流怎麼工作的呢?

最終列印結果