• Java之IO转换流


    IO转换流

    字符编码和字符集

    • 字符编码

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

      • 编码:字符(能看懂的)–字节(看不懂的)

      • 解码:字节(看不懂的)–字符(能看懂的)

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

        编码表:生活中文字和计算机中二进制的对应规则

    • 字符集

      • 字符集Charset:也叫编码表。是一个系统支持的所有字符的集合,包括各国家文字、标点符号、图形符号、数字等。
      • 计算机要准确的存储和识别各种字符集符号,需要进行字符编码,一套字符集必然至少有一套字符编码。常见字符集有ASCII字符集、GBK字符集、Unicode字符集等。
      • 当指定了编码,它所对应的字符集自然就指定了,所以编码才是我们最终要关心的。
      • ASCII字符集
        • ASCII是基于拉丁字母的一套电脑编码系统,用于显示现代英语,主要包括控制字符(回车键、退格、换行键等)和可显示字符(英文大小字符、阿拉伯数字和西文符号)。
        • 基本的ASCII字符集,使用7位(bits)表示一个字符,共128字符。ASCII的扩展字符集使用8位(bits)表示一个字符,共256字符,方便支持欧洲常用字符。
      • ISO-8859-1字符集
        • 拉丁表,别名Latin-1,用于显示欧洲使用的语言,包括荷兰、丹麦、德语、意大利语、西班牙语等。
        • ISO-5559-1使用单字节编码,兼容ASCII编码。
      • GBxxx字符集:
        • GB就是国标的意思,是为了显示中文而设计的一套字符集。
        • GB2312:简体中文码表。一个小于127的字符的意义与原来相同。但两个大于127的字符连在一起时,就表示一个汉字,这样大约可以组合了包含7000多个简体汉字,此外数学符号、罗马希腊的字母、日文的假名们都编进去了,连在ASCII里本来就有的数字、标点、字母都统统重新编了两个字节长的编码,这就是常说的“全角”字符,而原来在127号以下的那些就叫“半角”字符了。
        • GBK:最常用的中文码表。是在GB2312标准基础上的扩展规范,使用了双字节编码方案,共收录了21003个汉字,完全兼容GB2312标准,同时支持繁体汉字以及日韩汉字等。
        • **GB18030:**最新的中文码表。收录汉字70244个,采用多字节编码,每个字可以由1个、2个或4个字节组成。支持中国国内少数民族的文字,同时支持繁体汉字以及日韩汉字等。
      • Unicode字符集
        • Unicode编码系统为表达任意语言的任意字符而设计,是业界的一种标准,也称为统一码、标准万国码。
        • 它最多使用4个字节的数字来表达每个字母、符号,或者文字。有三种编码方案。UTF-8、UTF-16和UTF-32.最为常用的UTF-8编码。所以,我们开发Web应用,也要使用UTF-8编码。它使用一至四个字节为每个字符编码,编码规则:
          1. 128个US-ASCII字符,只需一个字节编码。
          2. 拉丁文等字符,需要二个字节编码。
          3. 大部分常用字(含中文),使用三个字节编码。
          4. 其他极少使用的Unicode辅助字符,使用四字节编码。

    编码引出的问题

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

      代码演示如下:

      package com.io.reversestream;
      
      import java.io.FileReader;
      import java.io.IOException;
      
      /*
            FileReader可以读取IDE默认编码格式(UTF-8)的文件
            FileReader读取系统默认编码(中文GBK)会产生乱码
       */
      public class ReverseStreamDemo01 {
          public static void main(String[] args) throws IOException {
              FileReader fr = new FileReader("C:\\abc\\我是GBK格式的文本.txt");
      
              int len = 0;
              while ((len = fr.read())!=-1){
                  System.out.println((char) len);
              }
              fr.close();
          }
      }
      
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21

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

    InputStreamReader类

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

    • InputStreamReader是从字节流到字符流的桥:它读取字节,并使用指定的charset将其解码为字符 。 它使用的字符集可以由名称指定,也可以被明确指定,或者可以接受平台的默认字符集。

      每个调用InputStreamReader的read()方法之一可能会导致从底层字节输入流读取一个或多个字节。 为了使字节有效地转换为字符,可以从底层流读取比满足当前读取操作所需的更多字节。

      为了最大的效率,请考虑在BufferedReader中包装一个InputStreamReader。 例如:

        BufferedReader in
         = new BufferedReader(new InputStreamReader(System.in)); 
      
      • 1
      • 2
    • 构造方法

      • InputStreamReader(InputStream in):创建一个使用默认字符集的字符流。

      • InputStreamReader(InputStream in, String charsetName):创建一个使用命名字符集的字符流。

      • 构造举例,代码如下:

        InputStreamReader isr = new InputStreamReader(new FileInputStream("in.txt"));
        InputStreamReader isr2 = new InputStreamReader(new FileInputStream("in.txt"),"GBK");
        
        
        • 1
        • 2
        • 3
    • 代码实例:

      package com.io.reversestream;
      
      import java.io.FileInputStream;
      import java.io.IOException;
      import java.io.InputStreamReader;
      
      /*
          java.io.InputStreamReader extends Reader
          InputStreamReader是从字节流到字符流的桥:它读取字节,并使用指定的charset将其解码为字符 。
      
          构造方法:
          InputStreamReader(InputStream in)创建一个使用默认字符集的InputStreamReader。
          InputStreamReader(InputStream in, String charsetName)创建一个使用命名字符集的InputStreamReader。
          参数:
               inputStream in:字符输入流,用来读取文件中保存的字节
               String charsetName:指定的编码表名称,不区分大小写,不指定默认utf-8
          使用步骤:
               1.创建InputStreamReader对象,构造方法中传递字节输入流和指定的编码表名称
               2.使用InputStreamReader对象中的方法read读取文件
               3.释放资源。
          注意事项:
               构造方法中指定的编码表名称要和文件的编码相同,否则会发生乱码
       */
      public class InputStreamReaderDemo01 {
          public static void main(String[] args) throws IOException {
              read_utf_8();
          }
      
          /*
              使用InputStreamReader对象,构造方法中传递字节输入流和指定的编码表名称
           */
          private static void read_utf_8() throws IOException {
              //1.创建InputStreamReader对象,构造方法中传递字节输入流和指定的编码表名称
              InputStreamReader isr = new InputStreamReader(new FileInputStream("C:\\abc\\utf_8.txt"));
              //2.使用InputStreamReader对象中的方法read读取文件
              int len = 0;
              while ((len = isr.read())!=-1){
                  System.out.println((char) len);
              }
              //3.释放资源
              isr.close();
      
          }
      }
      
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
      • 24
      • 25
      • 26
      • 27
      • 28
      • 29
      • 30
      • 31
      • 32
      • 33
      • 34
      • 35
      • 36
      • 37
      • 38
      • 39
      • 40
      • 41
      • 42
      • 43
      • 44
      • 45

    OutputStreamWriter类

    • OutputStreamWriter是字符的桥梁流以字节流:向其写入的字符编码成使用指定的字节charset 。 它使用的字符集可以由名称指定,也可以被明确指定,或者可以接受平台的默认字符集。

      每次调用write()方法都会使编码转换器在给定字符上被调用。 所得到的字节在写入底层输出流之前累积在缓冲区中。 可以指定此缓冲区的大小,但是默认情况下它大部分用于大多数目的。 请注意,传递给write()方法的字符不会缓冲。

      为了最大的效率,请考虑在BufferedWriter中包装一个OutputStreamWriter,以避免频繁的转换器调用。 例如:

        Writer out
         = new BufferedWriter(new OutputStreamWriter(System.out)); 
      
      • 1
      • 2
    • 构造方法

      • OutputStreamWriter(OutputStream out):创建一个使用默认字符编码的输出流。
      • OutputStreamWriter(OutputStream out, String charsetName):创建一个使用命名字符集的输出流。
    • 代码实例:

      package com.io.reversestream;
      
      import java.io.FileNotFoundException;
      import java.io.FileOutputStream;
      import java.io.IOException;
      import java.io.OutputStreamWriter;
      
      /*
          java.io.OutputStreamWriter extends Writer
          OutputStreamWriter是字符的桥梁流以字节流:向其写入的字符编码成使用指定的字节charset 。 它使用的字符集可以由名称指定,也可以被明确指定,或者可以接受平台的默认字符集。
      
          构造方法:
                OutputStreamWriter(OutputStream out)创建一个使用默认字符编码的OutputStreamWriter。
                OutputStreamWriter(OutputStream out, String charsetName)创建一个使用命名字符集的OutputStreamWriter。
                参数:
                     OutputStream out:字节输出流,可以用来写转换之后的字节到文件中
                     String charsetName:指定的编码表名称,不区分大小写,可以是utf-8等不指定默认使用Utf-8
           使用步骤:
                1.创建OutputStreamWriter对象,构造方法中传递字节输出流和指定的编码表名称
                2.使用OutputStreamWriter对象中的方法write,把字符转换为字节存储缓冲区中(编码)
                3.使用OutputStreamWriter对象中的方法flush,把内存缓冲区中的字节刷新到文件中(使用字节流写字节的过程)
                4.释放资源。
       */
      public class OutputStreamWriterDemo01 {
          public static void main(String[] args) throws IOException {
              //write_utf_8();
              write_gbk();
          }
      
      
          /*
               使用转换流OutputStreamWriter写GBK格式的文件
           */
      
          private static void write_gbk() throws IOException {
              //1.创建OutputStreamWriter对象,构造方法中传递字节输出流和指定的编码表名称
              OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("C:\\abc\\gbk.txt"), "GBK");
              //2.使用OutputStreamWriter对象中的方法write,把字符转换为字节存储缓冲区中(编码)
              osw.write("你好");
              //3.使用OutputStreamWriter对象中的方法flush,把内存缓冲区中的字节刷新到文件中(使用字节流写字节的过程)
              osw.flush();
              //4.释放资源
              osw.close();
      
          }
      
          /*
               使用转换流OutputStreamWriter写UTF-8格式的文件
           */
          private static void write_utf_8() throws IOException {
              //1.创建OutputStreamWriter对象,构造方法中传递字节输出流和指定的编码表名称
              OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("C:\\abc\\utf_8.txt"), "utf-8");
              //2.使用OutputStreamWriter对象中的方法write,把字符转换为字节存储缓冲区中(编码)
              osw.write("你好");
              //3.使用OutputStreamWriter对象中的方法flush,把内存缓冲区中的字节刷新到文件中(使用字节流写字节的过程)
              osw.flush();
              //4.释放资源
              osw.close();
      
          }
      }
      
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
      • 24
      • 25
      • 26
      • 27
      • 28
      • 29
      • 30
      • 31
      • 32
      • 33
      • 34
      • 35
      • 36
      • 37
      • 38
      • 39
      • 40
      • 41
      • 42
      • 43
      • 44
      • 45
      • 46
      • 47
      • 48
      • 49
      • 50
      • 51
      • 52
      • 53
      • 54
      • 55
      • 56
      • 57
      • 58
      • 59
      • 60
      • 61
      • 62

    练习:转换文件编码

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

    • 代码实例

      package com.io.reversestream;
      
      import java.io.*;
      
      /*
          练习:转换文件编码
                将GBK编码的文本文件,转换为UTF-8编码文件。
          分析:
                1.创建InputStreamReader对象,构造方法中传递字节输入流和指定的编码表名称GBK
                2.创建OutputStreamWriter对象,构造方法中传递字节输出流和指定的编码表名称UTF-8
                3.使用InputStreamReader对象中方法read读取文件
                4.使用OutputStreamWriter对象中的方法write,把读取的数据写入到文件中
                5.释放资源
       */
      public class TransDemo01 {
          public static void main(String[] args) throws IOException {
              //1.创建InputStreamReader对象,构造方法中传递字节输入流和指定的编码表名称GBK
              InputStreamReader isr = new InputStreamReader(new FileInputStream("C:\\abc\\gbk.txt"));
              //2.创建OutputStreamWriter对象,构造方法中传递字节输出流和指定的编码表名称UTF-8
              OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("C:\\abc\\utf_8.txt"));
              //3.使用InputStreamReader对象中方法read读取文件
              int len = 0;
              while ((len = isr.read())!=-1){
                  //4.使用OutputStreamWriter对象中的方法write,把读取的数据写入到文件中
                  osw.write(len);
              }
              //5.释放资源
              osw.close();
              isr.close();
          }
      }
      
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
      • 24
      • 25
      • 26
      • 27
      • 28
      • 29
      • 30
      • 31
      • 32
  • 相关阅读:
    【linux操作系统】xshell原理及Linux权限深度理解(入门必备)
    【Python】python多线程
    2023/10/1 -- ARM
    Cmake qt ,vtkDataArray.cxx.obj: File too big
    Unity-Input System新输入系统插件学习
    Linux调试器-gdb使用
    vue3 + vite常用工具
    作业 day4
    二元分类模型评估方法
    支付通道的安全性探讨
  • 原文地址:https://blog.csdn.net/qq_46080582/article/details/126439097