JAVA处理字符的原理。JAVA使用UNICODE来存储字符数据,处理字符时通常有三个步骤:
-
按指定的字符编码形式,从源输入流中读取字符数据
-
以UNICODE编码形式将字符数据存储在内存中
-
按指定的字符编码形式,将字符数据编码并写入目的输出流中。
JAVA处理字符时总是经过了两次编码转换,一次是从指定编码转换为UNICODE编码,一次是从UNICODE编码转换为指定编码。
如果在读入时,用错误的形式解码字符,则内存存储的是错误的UNICODE字符。
简单来说,就是用错误的编码方式解码了从输入流读取的字符数据,或用错误的编码方式将字符写入输出流,则下一个字符数据的接收者就会解码出错,从而导致最终显示乱码。
javac编译Java文件时,javac不会知道你所要编译的文件是什么类型,所以它需要指定读取文件所用的编码类型。
默认javac使用平台默认的字符编码类型来解析Java文件。而平台缺省(默认)编码是由操作系统决定的,我们使用的中午的操作系统的话平台缺省编码通常为GBK,可以使用System.getProperty("file.encoding")查看。
所以,javac会使用GBK来解析Java文件。如果要改变javac所用的编码类型,就要加上-encoding参数,如javac -encoding utf-8 Test.java,所以提前配置好项目和编译器的编码十分重要。
编译后字符数据会以UNICODE格式存入字节码文件中。然后编译器会调用java命令来运行此字节码文件。因为字节码中的字符总是 UNICODE格式,所以java读取字节码文件并没有编码转换过程。虚拟机读取文件后,字符数据便以UNICODE格式存储在内存中了。
调用System.out.println来输出字符发生字符编码转换,System.out.println使用了PrintStream类来输出字符数据至控制台。PrintStream会使用平台缺省的编码方式来输出字符,由于缺省的还是GBK所以会以GBK的形式输出。
举个例子:
有个以utf-8编码格式保存的txt文件,使用BufferedReader读取这个txt文件。
然后使用PrintStream将这个文件打印在控制台,如果再IDEA中,控制台设置的编码格式是GBK就会出现乱码,所以我们必须使用utf-8解码。这样就没有问题了。
像是这样 UTF-8 ->转码-> UNICODE ->解码-> UTF-8