Java 中文乱码
运行环境:Windows 10 ;IDEA-2019.3;Tomcat 9.0.24;jdk 1.8.0_221;
问题切入
我在idea中开发ssm框架的项目,然后直接在集成的tomat中运行,其他日志都是正常显示,唯独mybatis的参数日志中文乱码。
上面就是我遇到的具体乱码问题场景。从这个问题的出现,以及我解决的过程。让我有了写这篇文章的动机。
中文乱码,是我们这些中文世界的程序员常见到想吐的问题。发生的频率如此频繁。解决的方式也是如此碰运气。让我也是很气馁。每一次遇到中文乱码,就像遇到一个新问题,你不知道是哪个环节出了问题,你也不知道需要怎样的配置解决。全靠百度搜索,碰运气解决。
我思考了一通,尝试做个记录,尽量去发现解决的通用逻辑。
解决乱码问题,我想要通过这么几步,首先,要明白编码/解码原理;其次,要知道所有环节的默认编码;最后,要知道解决问题的配置方式的含义。
我也要按这个思路来梳理。
乱码底层原理分析
image.png画了个简单的图,如上面,正常情况下,解码和编码的过程中都要使用一致的编码格式。
如果发生乱码,考虑存在以下问题:
- 编码和解码的格式不一致。
- 编码时使用的编码格式不支持字符,当时就乱码了。解码时,使用一致的编码格式,也会乱码。
如果发生乱码,就要从上面的两种情况去考虑解决了。
所有环节的默认编码
这里,也是乱码问题最难解决的问题关键所在。因为,随着软件工业的发展,封装越来越厉害。终端使用者,根本不能知道终端使用之前,经历了多少个环节的编码和解码过程。所以,你去解决乱码问题,也只能是丈二和尚摸不着头脑了。
我这里也只能慢慢的穷举我知道的环节的默认编码。
- windows系统默认编码 : GBK
这也是很多乱码的源泉。程序员都在说要推进统一编码格式UTF-8。可是系统级别也没有使用UTF-8呀。 - Java文件编译后形成class默认编码:UTF-16编码
- JVM中的默认编码:受平台,配置影响。
- idea开发工具默认编码:idea本质也是一个java应用,还是遵循JVM的编码设置规则。
- tomcat服务器默认编码:tomcat本质也是一个java的应用,还是遵循JVM的编码设置规则。
- 源码文件默认编码:根据自己设定。
配置参数含义
-Dfile.encoding=UTF-8
-Dfile.encoding 解释:
在命令行中输入 java,在给出的提示中会出现 -D 的说明:
-D<name>=<value> # set a system property
-D 后面需要跟一个键值对,作用是设置一项系统属性
对 -Dfile.encoding=UTF-8 来说就是设置系统属性 file.encoding 为 UTF-8
那么 file.encoding 什么意思?字面意思为文件编码。
搜索 java 源码,只能找到 4 个文件中包含 file.encoding 的文件,
也就是说,只有四个文件调用了 file.encoding 这个属性。
在 java.nio.charset 包中的 Charset.java 中,这段话的意思说的很明确了。
简单说就是默认字符集是在 java 虚拟机启动时决定的,
依赖于 java 虚拟机所在的操作系统的区域以及字符集。
代码中可以看到,默认字符集就是从 file.encoding 这个属性中获取的。
-
idea集成tomcat后,tomcat的编码设置
image.png -
idea工具的编码设置
image.png
总结
我力图去理解乱码的问题解决,我后续还会继续充实此文。或者,随着我对编码的理解加深,也会推翻现在的逻辑。
附录:
有些段落引用自:http://yang3wei.github.io/blog/2013/02/10/java-dfile-dot-encoding-equals-utf-8-gan-diao-luan-ma/