Java 轉換流的簡單理解


字符編碼和字符集

字符編碼

計算機中儲存的信息都是用二進制數表示的,而我們在屏幕上看到的數字、英文、標點符號、漢字等字符是二進制數轉換之后的結果。按照某種規則,將字符存儲到計算機中,稱為編碼。反之,將存儲在計算機中的二進制數按照某種規則解析顯示出來,稱為解碼。比如說,按照A規則存儲,同樣按照A規則解析,那么就能顯示正確的文本符號。反之,按照A規則存儲,再按照B規則解析,就會導致亂碼現象。

編碼:字符 --> 字節

解碼:字節 --> 字符

  • 字符編碼,是一套自然語言的字符與二進制數之間的對應規則。

字符集

  • 字符集,也叫編碼表,是一個系統支持的所有字符集合,包括國家文字、標點符號、圖形符號、數字等。

計算機要准確的存儲和識別各種字符集符號,需要進行字符編碼,一套字符集必然至少有一套字符編碼。常見字符集有ASCII字符集、GBK字符集、Unicode字符集等。

編碼引出的問題

在IDEA中,使用FileReader讀取項目中的文本文件。由於IDEA的設置,都是默認的UTF-8編碼,所以沒有任何問題。但是,當讀取系統中創建的文本文件時,由於系統的默認是GBK編碼,就會出現亂碼。

那么該如何解決呢?我們可以使用InputStreamReader類、OutputStreamWriter類,指定編碼來進行讀寫操作,這時候就不會出現亂碼的情況了。

OutputStreamWriter類

java.io.OutputStreamWriter是字符流通向字節流的橋梁:可使用指定的charset將要寫入流中的字符編碼成字節(編碼)。它使用的字符集可以由名稱指定或顯式給定,否則將接受平台默認的字符集。

OutputStreamWriter類是java.io.Writer的子類,所以可以使用父類方法:

public void write(int c)
// 寫入單個字符。

public void write(char cbuf[])
// 寫入字符數組。

abstract public void write(char cbuf[], int off, int len)
// 寫入字符數組的某一部分,off是數組的開始索引,len是寫的字符個數。

public void write(String str)
// 寫入字符串。

public void write(String str, int off, int len)
//寫入字符的某一部分。off是字符的開始素,len是寫的字符個數。

abstract public void flush()
// 刷新該流的緩沖。

abstract public void close()
// 關閉此流,但會先刷新它。

構造方法

OutputStreamWriter(OutputStream out)
// 創建使用默認編碼的OutputStreamWriter對象

OutputStreamWriter(OutputStream out, String charsetName)
// 創建使用指定編碼的OutputStreamWriter對象
參數:
OutputStreamWriter out:字節輸出流
String charsetName:指定編碼表的名稱,不區分大小寫。如utf-8/UTF-8。

使用步驟:

1.創建OutputStreamWriter對象,構造方法中傳遞字節輸出流和指定的編碼表名稱。
2.使用OutputStreamWriter對象中的方法write,把字符轉換為字節存儲到緩沖區中(編碼)。
3.使用OutputStreamWriter對象中的方法flush,把內存緩沖區中的字節刷新到文件中(使用字節流寫字節的過程)。
4.釋放資源。

舉例:指定編碼,將數據保存到文件中。

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;

public class DemoOutputStreamWriter {
    public static void main(String[] args) throws IOException {
        Gbk_TXT();
    }

    private static void Gbk_TXT() throws IOException {
        // 創建OutputStreamWriter對象,構造方法中傳遞字節輸出流和指定的編碼表名稱。指定編碼為GBK。
        OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("/Users/liyihua/IdeaProjects/Study/src/view/study/demo35/OutputStreamWriter.txt"), "gbk");

        // 使用OutputStreamWriter對象中的方法write,把字符轉換為字節存儲到緩沖區中(編碼)。
        for (int i = 0; i < 5; i++) {
            osw.write("你好!" + i);
            osw.write("\n");
        }

        // 使用OutputStreamWriter對象中的方法flush,把內存緩沖區中的字節刷新到文件中(使用字節流寫字節的過程)。
        osw.flush();

        // 釋放資源。
        osw.close();
    }
}

運行,生成一個OutputStreamWriter.txt文件,文件內容如下:

img

由於IDEA默認編碼是UTF-8,這里使用了GBK編碼格式寫入數據進文件,所以在IDEA里面查看文件的內容出現亂碼。

InputStreamReader類

java.io.InputStreamReader是字節流通向字符流的橋梁:它使用指定的charset讀取字節並將其解碼為字符(解碼)。它使用的字符集可以由名稱指定或顯式給定,或者可以接受平台默認的字符集。

InputStreamReader類是java.io.Reader的子類,所以可以使用父類方法:

public void close()
// 關閉此流並釋放與此流相關聯的任何系統資源。

public int read()
// 從輸入流讀取一個字符。

public int read(char[] chars)
// 從輸入流中讀取一些字符,並將它們存儲到字符數組chars中。

構造方法

InputStreamReader(InputStream in)
// 創建默認字符集的InputStreamReader對象

InputStreamReader(InputStream in, String charsetName)
// 創建指定字符集的InputStreamReader對象
參數:
InputStream in:字符輸入流
String charsetName:指定編碼表的名稱,不區分大小寫。如gbk/GBK。

使用步驟:

1.創建InputStreamReader對象,構造方法中傳遞字節輸入流和指定的編碼表名稱。
2.使用InputStreamReader對象中的方法read,讀取文件。
3.釋放資源。

注意事項:構造方法中指定的編碼表名稱要和文件的編碼相同,否則會發生亂碼。

舉例:按指定解碼格式,讀取OutputStreamWriter.txt文件的內容

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;

public class DemoInputStreamReader {
    public static void main(String[] args) throws IOException {
        decode_GBK();
    }

    private static void decode_GBK() throws IOException {
        // 創建InputStreamReader對象,構造方法中傳遞字節輸入流和指定的編碼表名稱。
        InputStreamReader isr = new InputStreamReader(new FileInputStream("/Users/liyihua/IdeaProjects/Study/src/view/study/demo35/OutputStreamWriter.txt"), "GBK");

        // 使用InputStreamReader對象中的方法read,讀取文件。
        char[] chars = new char[25];
        while ((isr.read(chars)) != -1) {
            System.out.println(chars);
        }

        // 釋放資源。
        isr.close();
    }
}

控制台輸出:

你好!0
你好!1
你好!2
你好!3
你好!4

練習:轉換文件編碼

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

分析:

1.創建InputStreamReader對象,構造方法中傳遞字節輸入流和指定的編碼表名稱GBK。
2.創建OutputStreamWriter對象,構造方法中傳遞字節輸出流和指定的編碼表名稱UTF-8。
3.使用InputStreamReader對象中的方法read,讀取文件。
4.使用OutputStreamWriter對象中的方法write,把讀取的數據寫入到文件中。
5.釋放資源。

GBK.txt文件內容如下:

img

代碼實現:

import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.IOException;
import java.io.FileInputStream;
import java.io.FileOutputStream;

public class DemoInOutAndReaderWriter {
    public static void main(String[] args) throws IOException {
        method();
    }

    private static void method() throws IOException {
        // 創建InputStreamReader對象,構造方法中傳遞字節輸入流和指定的編碼表名稱GBK。
        InputStreamReader isr = new InputStreamReader(new FileInputStream("/Users/liyihua/IdeaProjects/Study/src/view/study/demo35/GBK.txt"), "GBK");

        // 創建OutputStreamWriter對象,構造方法中傳遞字節輸出流和指定的編碼表名稱UTF-8。
        OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("/Users/liyihua/IdeaProjects/Study/src/view/study/demo35/UTF_8.txt"), "UTF-8");

        // 使用InputStreamReader對象中的方法read,讀取文件。
        int len = 0;
        while ((len = isr.read()) != -1) {
            osw.write(len);
        }

        // 釋放資源。
        isr.close();
        osw.close();
    }
}

運行生成一個UTF_8.txt文件,文件內容如下:

img


免責聲明!

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



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