1 问题描述
最近刚将jdk从11版本升级到21版本后,在idea控制台输出中文出现乱码,这个问题查了很多资料都没有解决,相关的资料都是从统一修改为UTF-8编码、GBK编码以及修改为COMPAT的模式,这些问题都没有解决中文system.out输出中文乱码问题。
1.1 使用的idea版本
这个版本为2024版本的社区版
1.2 尝试过的方法
(1)尝试修改IDEA中setting中的File Encoding中的编码为UTF-8和GBK,但是都没有解决问题。
(2)尝试修改Eidt Custom VM Options的全局参数也没有解决问题。
e&pos_id=img-lXPiLTV7-1724468847502)
(3)按照修改VM Options为-Dfile.encoding=UTF-8或-Dfile.encoding=GBK的方法也依然还是乱码
2 解决办法
尝试了很多方法后,终于找到“关于IDEA控制台中文乱码问题”的解决方法才算真正解决了JDK21版本在IDEA控制台中文乱码的问题。具体的解决方法参考如下:
(1) JDK17及以前:在Custom VM Options中增加-Dfile.encoding=UTF-8
(2) JDK18:在Run->Edit Configurations中增加VM Options: -Dsun.stdout.encoding=UTF-8 -Dsun.stderr.encoding=UTF-8
(3) JDK19到JDK21:在Run->Edit Configurations中增加VM Options: -Dstdout.encoding=UTF-8 -Dstderr.encoding=UTF-8
在设置对应的参数时,其他上述提到的设置,建议都设置为UTF-8的编码,然后使用编码时,建议就使用Edit Configurations中增加VM Options的方法进行设置,不用设置为全局的参数,因为在idea中Edit Configurations中增加VM Options设置参数就是优先级别最高的。
3 原因分析
(1) 乱码的概念。在编程中,乱码是指由于字符编码和解码的算法不匹配而产生的错误。乱码问题产生的原因有很多,如编码格式不匹配、字符集不支持、字符集编码错误、字符集解码错误等。常见的支持中文编码方式有GB2312、GBK、GB18030、UTF-8、Unicode等。中文的乱码由于不同的编码错误解析就会出现编码错误,在java变成中编码错误出现是较为多的问题。
两种常用中文编码的说明
编码 | 解释 |
---|---|
GBK | 汉字内码扩展规范, 向下与 GB 2312 编码兼容,向上支持 ISO 10646.1国际标准,window中国区默认编码 |
UTF-8 | 针对Unicode的一种可变长度字符编码。兼容于ASCII编码, 国际比较通用的编码格式 |
(2) 要判断清楚是哪种乱码引起的,比如乱码可能是因为编码格式的问题,也可能是字符集的问题,也可能是字符集和编码格式的问题。参考IDEA乱码问题,原因&解决方式的方法,可以在System.out.println(str)
中将str的值设置为0信1息2信息3,通过编译运行看结果可以知道编码错误的问题。
原信息 | 原信息编码格式 | 解码方式 | 解码后显示 |
---|---|---|---|
0信1息2信息3 | ASCII,UTF_8,UTF_16, GBK | 同编码方式一样 | 0信1息2信息3 |
0信1息2信息3 | US-ASCII | US-ASCII,UTF-8,GBK | 0?1?2??3 |
0信1息2信息3 | US-ASCII | UTF-16 | 〿ㄿ㈿㼳 |
0信1息2信息3 | UTF-8 | US-ASCII | 0���1���2������3 |
0信1息2信息3 | UTF-8 | UTF-16 | ヤ뾡膯㋤뾡꼳 |
0信1息2信息3 | UTF-8 | GBK | 0淇�1鎭�2淇℃伅3 |
0信1息2信息3 | UTF-16 | US-ASCII,UTF-8 | �� 0O� 1o 2O�o 3 |
0信1息2信息3 | UTF-16 | GBK | � 0O� 1`o 2O醏o 3 |
0信1息2信息3 | GBK | US-ASCII | 0��1��2����3 |
0信1息2信息3 | GBK | UTF-8 | 」0��1Ϣ2��Ϣ3 |
0信1息2信息3 | GBK | UTF-16 | バ씱쾢㋐엏ꈳ |
实际操作,在写代码的过程中,升级为JDK21后,输出中文乱码
修改Vm Options参数,解决中文乱码问题
(3)为什么使用JDK1.8或JDK11等版本没有问题,但是在升级JDK19或21后之后就出现问题,JDK17及以前,标准输出流使用默认字符编码,而默认字符编码是在Java运行时启动时从操作系统获取的。具体原因为:①升级JDK版本导致的问题,JDK21版本中默认的编码为UTF-8,而之前版本默认为GBK,所以出现了乱码问题。②Windows11中中文的默认编码为GBK,而JDK21版本中默认的编码为UTF-8,所以出现了乱码问题。因此,网络很多的教程都是说通过设置file.encoding来设置编码,但是JDK21中已经不支持了,因为JDK21中已经默认使用UTF-8编码了。所以,JDK17及以前版本通过设置file.encoding就可以。JDK18,默认字符编码指定为UTF-8,修改file.encoding对这俩没有效果,也只能通过sun.stdout.encoding和sun.stderr.encoding来设置。到了JDK19及JDK21,新增了stdout.encoding和stderr.encoding两个属性,专门用来指定System.out和System.err的字符编码,如果不指定,还是只能从操作系统获取字符编码。
参考资料
https://blog.csdn.net/zhilan_note/article/details/139629768
https://blog.csdn.net/qq_39751227/article/details/125734085
https://blog.csdn.net/qq_45620215/article/details/134212593
https://www.jianshu.com/p/0e907a62743c