转换流

102 阅读5分钟

2.1 字符编码和字符集


字符编码

计算机中储存的信息都是用二进制数表示的,而我们在屏幕上看到的数字,英文,标点符号,汉字等字符是二进制数转换之后的结果。按照某种规则,将字符存储到计算机中,称为编码。反之,将存储在计算机中的二进制数按照某种规则解析显示出来,称为解码。比如说,按照A规则存储,同样按照A规则解析,那么就能显示正确的文本符号。反之,按照A规则存储,再按照B规则解析,就会导致乱码现象。

  • 字符编码(Character Encoding):就是一套自然语言的字符与二进制数之间的对应规则。

字符集

  • 字符集(Charset):也叫编码表,是一个系统支持的所有字符集的集合,包括各国家文字,标点符号,图形符号,数字。

计算机要准确的存储和识别各种字符集符号,需要进行字符编码,常见的字符集有ASCII字符集,GBK字符集,Unicode字符集等。

可见,当指定了编码,它对应的字符集就自然指定了,所以编码才是我们最需要关心的。

  • ASCII字符集:美国信息交换标准代码,是基于拉丁字母的一套电脑编码系统,用于显示现代英语,主要包括控制字符和可显示字符。基本的ASCII字符集,使用的是7位(bits)表示一个字符,共128个字符。ASCII的扩展字符集使用8位(bits)表示一个字符,共256字符,方便支持欧洲常用字符。
  • ISO-8859-1字符集:拉丁码表,用于显示欧洲使用的语言,使用单字节编码,兼容ASCII编码。
  • GBXXX字符集:GB就是国标的意思,是为了显示中文而设计的一套字符集。GBK:最常用的中文编码表,使用了双字节的编码方案。
  • Unicode字符集:Unicode编码系统为表达任意语言的任意字符而设计,是业界的一种标准,也称为万国码。它最多使用4个字节来表达每个字母,符号,或者文字。有三种编码方案,UTF-8,UTF-16,UTF-32,最为常用的就是UTF-8编码。

UTF-8编码,可以用来表示Unicode标准中的任何字符,它是电子邮件,网页及其他存储或传送文字的应用中优先采用的编码。互联网工作小组(IETF)要求所有互联网协议都必须支持UTF-8编码。所以,我们开发Web应用,也要使用UTF-8编码,它使用一到四个字节为每个字符编码,编码规则:

  • 128个US-ASCII字符,只需要一个字节编码
  • 拉丁等字符了,需要两个编码
  • 大部分常用字,含中文,使用三个字节编码
  • 其他极少使用的Unicode辅助字符,使用四字节编码。

2.2 编码引出的问题


在IDEA中,使用FileReader读取项目中的文本文件。由于IDEA的设置,都是默认的UTF-8编码,所以没有任何问题。但是当读取Windows系统中创建的文本文件的时候,由于Windows系统默认的是GBK编码,就会出现乱码。

private static void show1() {
        try (FileReader fileReader = new FileReader("E:\\01-尚硅谷MySQL核心技术-婷姐\\资料、代码\\note\\备注.txt");
        ) {
            int read;
            while ((read = fileReader.read()) != -1) {
                System.out.println((char) read);
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

那么如何读取GBK编码的文件呢?

2.3 InputStreamReader类


转换流 java.io.InputStreamReader,是Reader的子类,是从字节流到字符流的桥梁。它读取字节,并使用指定的字符集将其解码为字符。它的字符集可以由名称指定,也可以接受平台默认字符集。

构造方法

  • InputStreamReader(InputStream in):创建一个使用默认字符集的字符流
  • InputStreamReader(InputStream in,String charsetName):创建一个指定字符集的字符流

构造举例,代码如下:

  • InputStreamReader isr1=new InputStreamReader(new FileInputStream("in.txt"));
  • InputStreamReader isr2=new InputStreamReader(new FileInputStream("in.txt"),"GBK");
private static void show2() {
        //定义文件路径,文件为GBK编码
        String FileName = "E:\\01-尚硅谷MySQL核心技术-婷姐\\资料、代码\\note\\备注.txt";
        //创建流对象,默认为UTF8编码
        try (InputStreamReader isr1 = new InputStreamReader(new FileInputStream(FileName));
             InputStreamReader isr2 = new InputStreamReader(new FileInputStream(FileName),"GBK");

        ) {
            //定义变量,保存字符
            int  read;
            //使用默认的编码字符流读取,乱码
            while ((read = isr1.read()) != -1) {
                System.out.print((char) read);
            }


            System.out.println();

            //使用指定编码的字符流读取,正常解析
            while ((read = isr2.read()) != -1) {
                System.out.print((char) read);
            }


        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }


2.4 OutputStreamWriter类


转换流 java.io.OutputStreamWriter,是Writer的子类,是从字符流到字节流的桥梁。使用指定的字符集将字符编码为字节。它的字符集可以由名称指定,也可以接受平台的默认字符集。

构造方法

  • OutputStreamWriter(OutputStream in):创建一个使用默认字符集的字符流。
  • OutputStreamWriter(OutputStream in,String charsetName): 创建一个指定的字符集的字符流

构造举例,代码如下:

  • OutputStreamWriter isr1=new OutputStreamWriter(new FileOutputstream("out.txt"));
  • OutputStreamWriter isr2=new OutputStreamWriter(new FileOutputStream("out.txt"),"GBK");
private static void show3() {
        //定义文件路径
        String FileName = "E:\\01-尚硅谷MySQL核心技术-婷姐\\资料、代码\\note\\备注.txt";
        //创建流对象,默认UTF8编码
        try (OutputStreamWriter osw1 = new OutputStreamWriter(new FileOutputStream(FileName, true));
             OutputStreamWriter osw2 = new OutputStreamWriter(new FileOutputStream(FileName, true), "GBK");

        ) {

            //写出数据
           // osw1.write("你好");

            osw2.write("你好");


        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

2.5 练习:转换文件编码


将GBK编码的文件,转换为UTF-8编码的文本文件。

案例分析

  1. 指定GBK编码的转换流,读取文本文件
  2. 使用UTF-8编码的转换流,写出文本文件
private static void show4() {
        //定义文件路径
        String srcFile = "E:\\01-尚硅谷MySQL核心技术-婷姐\\资料、代码\\note\\备注.txt";
        String desFile = "a.txt";

        //创建流对象
        //转换输入流,指定GBK编码
        try (InputStreamReader isr = new InputStreamReader(new FileInputStream(srcFile), "GBK");
             OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream(desFile), "UTF-8")
        ) {
            //读写数据,定义数组
            char[] cbuf = new char[1024];

            //定义长度
            int len;

            //循环读取
            while ((len = isr.read(cbuf)) != -1) {
                osw.write(cbuf, 0, len);
            }




        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }


    }