上来一张图:
一、jvm默认编码(字符串)
JVM内部编码是UTF-16(JVM中字符串格式为UTF-16),下文所指的默认编码都是指JVM IO流的编码。
可以使用System.out.println(Charset.defaultCharset());来查看jvm默认的字符集
JVM的字符集编码取的是操作系统默认的字符集编码
Java 中,字符字节转换时,如果不提供字符集,使用JVM默认字符集。例如,字符串和字节数组转换时,字节流和字符流转换时等。
jvm默认编码的更改:
1)更改JVM参数 -Dfile.encoding=UTF-8
2)使用gradle设置默认编码
tasks.withType(JavaCompile){
options.encoding="UTF-8"
}
为什么在程序中更改file.encoding的时候不生效?
当我们在改变System.getProperties里的file.encoding 的时候,defaultCharset已经被初始化过了(有些IO操作中对defaultCharset的操作是只能被初始化一次),所以不会在调用初始化的代码。所以JVM启动后设置系统配置值System.setProperty("file.encoding", "UTF-8")不会影响到这个字符集的编码。
二、java文件编译默认编码
是Java源码编译器负责将Java源码文件的编码转换为最终的UTF-8。可能会导致乱码的不是Java源码编译器的“编码”(写出UTF-8)的过程,而是“解码”(读入Java源码内容)的过程。
例子:如果A.java文件使用GBK编码,而使用UTF-8读入java源码,则会在编译时产生转码报错
如官方文档,如果不指定encoding,则使用平台默认的转换器。
-encoding_encoding_Set the source file encoding name, such as EUC-JP and UTF-8. If
-encoding is not specified, the platform default converter is used.
可以通过-encoding更改encoding
2.1 IDEA等编译器编译java文件
我习惯把 IDEA的编码设置成UTF-8。那么每个项目中的java源文件的编码就是UTF-8。这样编译也从没有问题,也没有出现过乱码。正是因为这样才掩盖了使用javac可能出现的乱码。那么Eclipse是如何正确编译文件编码为UTF-8的java源文件的呢?唯一的解释就是Eclipse自动识别了我们java源文件的文件编码,然后采取了正确的encoding参数来编译我们的java源文件。功劳都归功于IDE的强大了。
三、内存中字符串的编码
内存中的字符串不仅仅局限于从class代码中直接加载而来的字符串,还有一些字符串是从文本文件中读取的,还有的是通过数据库读取的,还有可能是从字节数组构建的,然而他们基本上都不是Unicode编码的,原因很简单,存储优化。
因此就需要处理各种各样的编码问题,在处理之前,必须明确“源”的编码,然后用指定的编码方式正确读取到内存中。如果是一个方法的参数,实际上必须明确该字符串参数的编码,因为这个参数可能是另外一个日文系统传递过来的。当明确了字符串编码时候,就可以按照要求正确处理字符串,以避免乱码。
参考:深入浅出java编码