49.字符编码与转换流

转换流

注意:JVM内部使用的编码方式为默认编码方式为系统的编码方式(当然可以自己设置),但是在IEDA中,会把默认当前运行的JVM的编码方式改成UTF-8!
而python解释器在内存中是使用的Unicode编码!

修改JVM默认编码方式!

  1. 在系统的环境变量中添加一个变量,名为: JAVA_TOOL_OPTIONS, 值为:-Dfile.encoding=UTF-8
  2. 在运行java程序的时候指定参数java -Dfile.encoding=UTF-8 Test【注意:第2种方式每次运行时都需要指定
  3. 如果是web工程,可以在catalina.bat的最前面加入set JAVA_OPTS=-Dfile.encoding=UTF-8;设置了编码后使用java -help可能会出现乱码,这个时候可以使用-Duser.language=en设置一下语言

一、字符编码

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

@@@@@@@@@@@ <-------decoded解码------------------ 1010101010
【数字,英文】
【标点符号】----------------------(编码规则)---------------------【底层二进制】
【汉字】
@@@@@@@@@@@ --------encoding编码-------------------> 1010101010
如果解码的规则和编码的规则不同,就会出现乱码的现象!

二、字符集

  • 字符集Charset: 编码表。系统支持的所有字符的集合,包括各国国家文字、标点符号、图形符号、数字等。

常见的字符集:ASCII、GBK、Unicode、UTF-8等。

字符集与编码规则.png
  • ASCII:(不超过1字节)**

    • 基于拉丁字母、用于显示英文、包含控制字符(回车等)、显示字符
    • 基本的ASCII使用7bits表示一个字符(128个字符),拓展的使用8bits(256个字符)。
  • Unicode:(统一4字节编码)**

    • 标准万国码,国际标准、有三种优化编码方案:UTF-8【常用】、UTF-16、UTF-32
    • UTF-8(1-4个字节):: 一个压缩版的Unicode(空间压缩,使用1-4个字节为每个字符编码,节省空间,根据编码规则及编码头的数字可以准确判断是对应的多少字节)
      • 编码规则:
        • 128个US-ASCII字符:1个字节编码
        • 拉丁文等:2个字节编码
        • 大部分常用字(包含中文):3个字节编码
        • 极少使用的Unicode辅助字符:4个字节编码
  • GB(xxx):为中文显示而设计的

    • GB2312:简体中文码表。一个小于127的字符的意义与原来相同。但两个大于127的字符连在一起时,就表示一个汉字,这样大约可以组合了包含7000多个简体汉字,此外数学符号、罗马希腊的字母、日文的假名们都编进去了,连在ASCII里本来就有的数字、标点、字母都统统重新编了两个字节长的编码,这就是常说的"全角"字符,而原来在127号以下的那些就叫"半角"字符了。
    • GBK: 最常用的(一个汉字两个字节),扩展了GB2312,双字节编码方法,共收录了21003个汉字,完全兼容GB2312标准,同时支持繁体汉字以及日韩汉字等
    • GB18030: 最新的中文码表,收录汉字70244个,采用多字节编码,每个字可以由1个、2个或4个字节组成。支持中国国内少数民族的文字,同时支持繁体汉字以及日韩汉字等。
  • ISO-8859-1:拉丁码表、Latin-1、欧洲使用、一个字节编码,兼容ASCII

三、InputStreamReader

转换流java.io.InputStreamReaderReader的子类、字节流字符流 的桥梁,读取字节,使用指定的字符集将其解码为字符。可指定名称、可接受系统默认编码方式。

1.构造方法(省略public)

  • InputStreamReader(InputStream in) : 创建一个使用默认字符集的字符流,使用系统的编码方式。

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

    • 继承自父类的方法:int read()、int read(char[] cbuf)、void close()
    • InputStream抽象接口一般肯定是使用FileInputStream!
      - 使用步骤:
      1. 创建InputStreamReader对象,构造方法中传递字节输入流和指定的编码表名称
      2. 使用InputStreamReader对象中的方法read读取文件
      3. 释放资源
      - 注意事项:构造方法中指定的编码表名称要和文件的编码相同,否则会发生乱码

  • 案例:使用指定字符集读取文件!BufferedReader 结合 InputStreamReader 再结合 FileInputStream 使用

/**@指定字符级
* BufferedReader(需要传入Reader -- InputStreamReader)
* InputStreamReader是Reader的子类,
* InputStreamReader(需要传入InputStream -- FileInputStream)
*/
InputStreamReader isr = new InputStreamReader(new FileInputStream("F:\\test\\GBK.txt"), "GBK");
BufferedReader br = new BufferedReader(isr);
System.out.println(br.readLine());
br.close();
isr.close();

// 我是GBK编码的,哈哈,必须的使用GBK编码方式才能读出来知道不!

四、OutputStreamWriter

转换流 java.io.OutputStreamWriter ,Writer子类,字符流到字节流的桥梁,可使用操作系统默认字符集将字符编码为字节。字符集也可以由名称指定。

1.构造方法(省略public)

  • OutputStreamWriter(OutputStream out) : 创建一个使用默认字符集的字符流
  • OutputStreamWriter(OutputStream out, String charsetName): 创建一个指定字符集的字符流
    • 继承父类的方法:write(int c)、write(char[] cbuf)、write(char[] cbuf, int off, int len)、write(String str)、write(String str, int off, int len)、flush()、close()
      -使用步骤:
      1. 创建OutputStreamWriter对象,构造方法中传递字节输出流和指定的编码表名称
      2. 使用OutputStreamWriter对象中的方法write,把字符转换为字节存储缓冲区中(编码)
      3. 使用OutputStreamWriter对象中的方法flush,把内存缓冲区中的字节刷新到文件中(使用字节流写字节的过程)
      4. 释放资源
        使用指定编码写出
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("F:\\test\\UTF-8.txt"), "UTF-8");
BufferedWriter bw = new BufferedWriter(osw);
osw.write("UTF-8编码方式");
osw.close();
osw.close();

转换流是字节与字符间的桥梁

转换流是字节与字符间的桥梁.png

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

// GBK编码内容:我是GBK编码的,哈哈,必须得使用GBK编码方式才能读出来知道不!
String line;
InputStreamReader isr = new InputStreamReader(new FileInputStream("F:\\test\\GBK.txt"), "GBK");
BufferedReader br = new BufferedReader(isr);
line = br.readLine();
br.close();
isr.close();

OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("F:\\test\\UTF-8.txt"), "UTF-8");
BufferedWriter bw = new BufferedWriter(osw);
osw.write(line);
osw.close();
osw.close();

IDEA中,JVM运行使用的编码方式!

// GBK编码内容: 我
String line;
InputStreamReader isr = new InputStreamReader(new FileInputStream("F:\\test\\GBK.txt"), "GBK");
BufferedReader br = new BufferedReader(isr);
line = br.readLine();
br.close();
isr.close();

System.out.println("内容:‘" +  line + "’ 编码方式GBK  ,外存中大小2字节,JVM中 " +  line.getBytes().length + "字节");

// UTF-8编码内容:我
InputStreamReader isr2 = new InputStreamReader(new FileInputStream("F:\\test\\UTF-8.txt"), "UTF-8");
BufferedReader br2 = new BufferedReader(isr2);
line = br2.readLine();
br2.close();
isr2.close();

System.out.println("内容:‘" +  line + "’ 编码方式UTF-8,外存中大小3字节,JVM中 " +  line.getBytes().length + "字节");

/** IDEA中
 * 内容:‘我’ 编码方式GBK  ,外存中大小2字节,JVM中 3字节
 * 内容:‘我’ 编码方式UTF-8,外存中大小3字节,JVM中 3字节
 */

中国境内的win环境下

// GBK: One Character(我)
String line;
InputStreamReader isr = new InputStreamReader(new FileInputStream("GBK.txt"), "GBK");
BufferedReader br = new BufferedReader(isr);
line = br.readLine();
br.close();
isr.close();

System.out.println("content:" +  line + "GBK   OutMemory 2; In JVM: " +  line.getBytes().length + " bytes");

//GBK: One Character(我)
InputStreamReader isr2 = new InputStreamReader(new FileInputStream("UTF-8.txt"), "UTF-8");
BufferedReader br2 = new BufferedReader(isr2);
line = br2.readLine();
br2.close();
isr2.close();

System.out.println("content:" +  line + "UTF-8 OutMemory 3; In JVM: " +  line.getBytes().length + " bytes");

/*
content:我GBK   OutMemory 2; In JVM: 2 bytes
content:我UTF-8 OutMemory 3; In JVM: 2 bytes
*/
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容