Java IO流詳解(六)----轉換流(字節流和字符流之間的轉換)


轉換流也是一種處理流,它提供了字節流和字符流之間的轉換。在Java IO流中提供了兩個轉換流:InputStreamReader 和 OutputStreamWriter,這兩個類都屬於字符流。其中InputStreamReader將字節輸入流轉為字符輸入流,繼承自Reader。OutputStreamWriter是將字符輸出流轉為字節輸出流,繼承自Writer。

 

眾所周知,計算機中存儲的數據都是二進制的數字,我們在電腦屏幕上看到的文字信息是將二進制轉換之后顯示的,兩者之間存在編碼解碼的過程,其互相轉換必須遵循某種規則,即編碼和解碼都遵循同一種規則才能將文字信息正常顯示,如果編碼跟解碼使用了不同的規則,就會出現亂碼的情況。

  • 編碼:字符、字符串(能看懂的)--字節(看不懂的)
  • 解碼:字節(看不懂的)-->字符、字符串(能看懂的)

 

上面說的編碼與解碼的過程需要遵循某種規則,這種規則就是不同的字符編碼。我們在剛剛學習編程的時候最早接觸就是ASCII碼,它主要是用來顯示英文和一些符號,到后面還有接觸到別的編碼規則常用的有:gb2312,gbk,utf-8等。它們分別屬於不同的編碼集。

我們需要明確的是字符編碼和字符集是兩個不同層面的概念。

  • encoding是charset encoding的簡寫,即字符集編碼,簡稱編碼
  • charset是character set的簡寫,即字符集

編碼是依賴於字符集的,一個字符集可以有多個編碼實現,就像代碼中的接口實現依賴於接口一樣。

轉換流的原理是:字符流 = 字節流 + 編碼表。在轉換流中選擇正確的編碼非常的重要,因為指定了編碼,它所對應的字符集自然就指定了,否則很容易出現亂碼,所以編碼才是我們最終要關心的。

轉換流的特點:其是字符流和字節流之間的橋梁。

       可對讀取到的字節數據經過指定編碼轉換成字符

       可對讀取到的字符數據經過指定編碼轉換成字節

那么何時使用轉換流?

       當字節和字符之間有轉換動作時

       流操作的數據需要編碼或解碼時

 

1、InputStreamReader

InputStreamReader是字節流到字符流的橋梁:它讀取字節,並使用指定的字符集將其解碼為字符。它的字符集可以由名稱指定,也可以接受平台的默認字符集。

構造方法:

  • InputStreamReader(InputStream in):創建一個默認字符集字符輸入流。
  • InputStreamReader(InputStream in, String charsetName):創建一個指定字符集的字符流。

構造方法示例代碼:

    InputStreamReader isr1 = new InputStreamReader(new FileInputStream("D:\\IO\\utf8.txt"));
    InputStreamReader isr2 = new InputStreamReader(new FileInputStream("D:\\IO\\utf8.txt"),"UTF-8");

InputStreamReader讀入不同編碼舉例(讀入的文件編碼是UTF-8):

package com.thr;

import java.io.*;

/**
 * @author Administrator
 * @date 2020-02-27
 * @desc InputStreamReader
 */
public class InputStreamReaderTest {
    public static void main(String[] args) {
        //定義轉換流
        InputStreamReader isr = null;
        InputStreamReader isr1 = null;

        try {
            //創建流對象,默認編碼方式
            isr = new InputStreamReader(new FileInputStream("D:\\IO\\utf8.txt"));
            //創建流對象,指定GBK編碼
            isr1 = new InputStreamReader(new FileInputStream("D:\\IO\\utf8.txt"),"GBK");

            //默認方式打印
            int len;
            char[] buffer = new char[1024];
            while ((len=isr.read(buffer))!=-1){
                System.out.println(new String(buffer,0,len));
            }
            //GBK編碼方式打印
            int len1;
            char[] buffer1 = new char[1024];
            while ((len1=isr1.read(buffer1))!=-1){
                System.out.println(new String(buffer1,0,len1));
            }

            System.out.println("成功...");
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //釋放資源,先使用的后關閉
            if (isr1!=null){
                try {
                    isr1.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (isr!=null){
                try {
                    isr.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}
//運行結果:
--UTF-8
武漢加油
中國加油
齊心協力
戰勝疫情
--GBK
鍩挎奼夊姞娌�
涓浗鍔犳補
榻愬績鍗忓姏
鎴樿儨鐤儏

可以發現,UTF-8編碼沒有出現亂碼,而GBK編碼出現了亂碼,這是因為是在IDEA編輯器下打印的,我的IDEA編輯器設置的默認編碼是UTF-8。而UTF-8的編碼集是Unicode,GBK的編碼集是GBK,兩者並沒有通過轉換,所以GBK編碼在Unicode集上打印出現了亂碼。

 

2、OutputStreamWriter

OutputStreamWriter是字符流通向字節流的橋梁:用指定的字符集將字符編碼為字節。它的字符集可以由名稱指定,也可以接受平台的默認字符集。

構造方法:

  • OutputStreamWriter(OutputStream in): 創建一個使用默認字符集的字符流。
  • OutputStreamWriter(OutputStream in, String charsetName): 創建一個指定字符集的字符流。

構造方法示例代碼:

    OutputStreamWriter isr1 = new OutputStreamWriter(new FileOutputStream("D:\\IO\\gbk.txt""));
    OutputStreamWriter isr2 = new OutputStreamWriter(new FileOutputStream("D:\\IO\\gbk1.txt") , "GBK");

OutputStreamWriter讀出不同編碼舉例:

package com.thr;

import java.io.*;

/**
 * @author Administrator
 * @date 2020-02-27
 * @desc OutputStreamWriter
 */
public class OutputStreamReaderTest {
    public static void main(String[] args) {
        //定義轉換流
        OutputStreamWriter osw = null;
        OutputStreamWriter osw1 = null;

        try {
            osw = new OutputStreamWriter(new FileOutputStream("D:\\IO\\gbk.txt"));
            osw1 = new OutputStreamWriter(new FileOutputStream("D:\\IO\\gbk1.txt"),"GBK");
            //以默認格式寫出
            osw.write("武漢加油,中國加油");
            //以GBK格式寫出
            osw1.write("武漢加油,中國加油");

            System.out.println("成功...");
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //釋放資源,先使用的后關閉
            if (osw1!=null){
                try {
                    osw1.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (osw!=null){
                try {
                    osw.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

我們運行完后發現並沒有亂碼,這是因為Windows系統默認支持了UTF-8和GBK字符集。可以將輸出的路徑改為當前項目下 new FileOutputStream(“gbk.txt”);然后用Idea打開就可以看成差別來了。

 

3、轉換文件編碼

將UTF-8編碼的文本文件,轉換為GBK編碼的文本文件。

    1、指定UTF-8編碼的轉換流,讀取文本文件。

    2、使用GBK編碼的轉換流,寫出文本文件。

image

package com.thr;

import java.io.*;

/**
 * @author Administrator
 * @date 2020-02-27
 * @desc 將讀入UTF-8文件轉換為GBK
 */
public class ConversionStreamTest {

    public static void main(String[] args) {
        //定義轉換流
        InputStreamReader isr = null;
        OutputStreamWriter osw = null;

        try {
            //創建流對象,指定GBK編碼
            isr = new InputStreamReader(new FileInputStream("D:\\IO\\utf8.txt"),"UTF-8");
            osw = new OutputStreamWriter(new FileOutputStream("gbk.txt"),"GBK");

            int len;
            char[] buffer = new char[1024];
            while ((len=isr.read(buffer))!=-1){
                osw.write(buffer,0,len);
            }
            System.out.println("成功...");
        }  catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //釋放資源
            if (osw!=null){
                try {
                    osw.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (isr!=null){
                try {
                    isr.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM