1. 程式人生 > >IO流第六課轉換流

IO流第六課轉換流

  這節課來講講轉換流

 

  在講轉換流之前了,我們先講講字元的編碼與解碼。

 

  首先,我們知道計算機裡所有資料都是以二進位制的形式儲存的,.java檔案想要執行必須先被編譯成.class位元組碼檔案,這裡我們提到了一個詞,位元組碼,或者說位元組,以往一直沒機會,這次就來帶大家看看位元組碼檔案。

 

 

這些以.class為字尾名的檔案就是.class檔案,這些檔案的內容全是位元組。我們開啟來看看

 

看不懂,對不對?我也看不懂,因為這是給計算機看的。

 

人看的懂的是字元,計算機能看懂的是位元組,那麼如何將計算機看得懂的位元組變成人看得懂的字元呢?又如何將人看得懂的字元變成計算機看得懂的位元組呢?

 

編碼:

  將字元轉換成位元組的過程叫編碼,編碼指按照一定的規則將字元轉換成位元組

 

解碼:

  將位元組轉換車字元的過程叫解碼,解碼值按照一定的規則將位元組轉換成字元

 

下面來看一段java程式碼

看介紹裡可以看出String 的構造器可以對位元組進行解碼,而且可以按照指定的字符集進行解碼

 

說一下字符集: 就是一種編碼或者解碼的規則,常見的字符集有: GBK,gb2312,UTF-8(這個我們以後用的最多)

 

 

String 可以解碼,自然也提供了編碼的方法,就是使用getBytes方法。

 

 

Demo 01:

public static void main(String[] args) throws UnsupportedEncodingException {



    //先來new一個byte陣列

    byte[] bytes = "我愛java".getBytes("UTF-8");



    String str = 
new String(bytes, "UTF-8");     System.out.println(str); }

 

輸出:

 Java

 

注意: 如果編碼字符集和解碼字符集不相同的話,會出現亂碼

 

 

 

 

 

 

 

 

Demo 02:

public static void main(String[] args) throws UnsupportedEncodingException {



    //先來new一個byte陣列

    byte[] bytes = "我愛java".getBytes("UTF-8");



    String str = new String(bytes, "GBK");



    System.out.println(str);

}

 

輸出:

鎴戠埍java

 

順便一提:如果字符集不同的話,只有不在0-127之間的字元才會出現亂碼

 

 

接下來看看亂碼的第二個原因: 位元組不完整

 

首先有一個問題,把一個字元轉換成一個位元組陣列,那麼這個位元組陣列的長度是多少?

 

Demo 03:        

public static void main(String[] args) throws UnsupportedEncodingException {



    byte[] bytes = "1".getBytes();



    System.out.println(bytes.length);   //1



    bytes = "a".getBytes();

    System.out.println(bytes.length);   //1



    bytes = "我".getBytes();
System.out.println("我".length());   //1

    System.out.println(bytes.length);   //3

}

 

結論: 0-127之間的字元轉位元組一個字元對應一個位元組,中文的一個漢字對應3個位元組,而且,一個漢字只是一個字元

 

Demo 04:

public static void main(String[] args) throws UnsupportedEncodingException {



    byte[] bytes = "我".getBytes();

    

    String str = new String(bytes,0,1);

    System.out.println(str);    //亂碼

    str = new String(bytes,0,3);

    System.out.println(str);    //正常

}

 

結論: 亂碼的第二個原因: 位元組不完整

 

OK,講清楚編碼和解碼之後,我們再來講講轉換流 。

 

轉換流: 將位元組流轉換成字元流的流,主要作用是處理字元編碼

 

轉換流常用的兩個類: InputStreamReader, OutputStreamWriter

 

 

InputStreamReader:

InputStreamReader 是位元組流通向字元流的橋樑:它使用指定的 charset 讀取位元組並將其解碼為字元。它使用的字符集可以由名稱指定或顯式給定,或者可以接受平臺預設的字符集。

構造器:

 

主要用最後一個 InputSteamReader(InputStream in, String charsetName)

 

 

下面來看一個小例子:

 

 

Demo 05:

public static void main(String[] args) throws FileNotFoundException, UnsupportedEncodingException {

        //這裡我麼有異常直接丟擲,就不捕獲了,方便看



//        BufferedReader reader = new BufferedReader(new FileReader(new File("F:\\code\\java\\2.txt")));

        //這裡我們就發現了一個問題,我們在用字元流讀取檔案的時候,沒辦法指定字符集編碼,這是有很大問題的

        //因為編譯器的預設編碼可能和檔案的編碼不一樣,這樣就會造成亂碼的現象

        //所以我們希望能指定編碼,同時又去用字元流去讀取(加緩衝流是提高效率),這個時候就需要轉換流

        //轉換流有兩個: InputStreamReader, OutputStreamWriter

        

        //這樣我們就可以使用指定字符集編碼的字元緩衝流來讀取檔案了,看起來有點麻煩,實際上了解了原理以後非常的好寫,我們來重新寫一遍



        /**

         * 第一步 new一個BufferedReader,構造器需要一個Reader型別的引數

         * 第二步 由於轉換流InputStreamReader是Reader的子類,所以可以把InnputStreamReader物件 傳進去

         * 第三步 InputStreamReader需要一個InputStream 和 一個 字串(表示字符集編碼)

         */

        BufferedReader reader = new BufferedReader(

                new InputStreamReader(new FileInputStream(new File("F:\\code\\java\\2.txt")), "UTF-8")

        );   

        //這樣,一個可以指定字元編碼集的字元 緩衝流就構造好了,剩下的就和以前講的一樣即可

        //OutputStreamWriter和InputStreamReader差不多,只不過一個讀,一個寫

        BufferedWriter writer = new BufferedWriter(

                new OutputStreamWriter(new FileOutputStream(new File("F:\\code\\java\\3.txt")),"UTF-8")

        );

    }