Java乱码问题(如何产生,怎么解决)
背景
(背景部分只是个引子,并不很重要,不感兴趣的话可以直接跳过,从思考部分开始看起)
最近因公司项目需要,使用javaFx开发了一个桌面客户端。因为客户群都是windows桌面,所以我采用了maven的javapackager插件将其打包成exe安装文件。
然后,就遇到了中文乱码问题,下意识的百度了一下,看到几种方法,总结下来有以下几种:
- idea的encoding配置(有说是全部改成utf8的成功的,有说全改成GBK成功的)
- 启动选项中加
java -jar app.jar -Dfile.encoding=UTF-8
- 在maven配置中添加
<properties>
<maven.compiler.encoding>UTF-8</maven.compiler.encoding>
</properties>
结果是,每种我都试了,但我运气没别人好,没成功啊!!!
思考
然后我静下心来想了想,还是我自己懒惰了,不愿意动脑子,想走捷径,这显然是不对的。
于是乎,我开始仔细思考问题到底出在哪?
乱码产生的原理
乱码是怎么产生的呢?这个对于我来说没有太多的障碍,因为我在刚入行时候花了很长一段时间研究它,最后弄明白了。这里不讲很多理论的东西,就打个比方。
比如:小明是一个中国人,从小精通汉语拼音的读写。有一天小明收到了一份来自外国友人的微信漂流瓶,上面写着:hello world。然后小明开始利用学过的汉语拼音翻译这句话:和llo 我rld。小明瞬间就懵了,乱码了,看不懂啊!!!
在我们平时的开发中,一个java文件就是一封信,这封信的内容通常被一个叫UTF-8的方法编码成一串0101010存储在磁盘上。而我们知道,java文件要被编译成class文件才能被JVM执行。这里就需要有一段程序他要认识UTF-8生成的010101,然后再把它编译成class文件,而class文件会用UNICODE将字符串编码存储在磁盘上(为什么用 UNICODE 呢?因为 UNICODE 可以表示一切字符)。最后就是运行,JVM读取class文件,然后开始运行,这时候 JVM 加载到内存中的字符串是 UNICODE编码的,可以按照输出要求转换成其他编码,比如通过System.out.println("你好")
会转换成系统默认编码进行输出,可以看下面例子。
例子
我有一个如下的java文件:
public class LuanMa{
public static void main(String[] args){
System.out.print("我是中国人");
}
}
step1. 首先我要确保这个java文件是UTF-8编码的,然后这里的"我是中国人"被编码成:6211662F4E2D56FD4EBA存在磁盘上。
step2. 使用javac编码此文件,此时会先读取出此文件的内容,然后使用UTF-8读到了6211662F4E2D56FD4EBA这个字符串,将其转换成 UNICODE(\u6211\u662f\u4e2d\u56fd\u4eba)编码写到了class文件中。
step3. JVM读入刚刚编译的class文件。它也是使用UNICODE的形式读的,读到了 \u6211\u662f\u4e2d\u56fd\u4eba ,然后转换为系统默认编码传递给命令行工具,命令行工具通过其默认编码解析出来之后输出我是中国人几个汉字显示在了屏幕上。这里要注意,如果你的命令行工具输出的编码不是系统默认编码,也会乱码!
!!!划重点:非常显然:
- 只要保证文件本身编码和编译使用的编码一致,则编译出来的 class 文件没有问题,
- 只要保证系统默认编码和命令行工具输出编码一致,字符串就不会乱码。
解决方案
有了上面的理论基础,按部就班就很容易解决上面遇到的乱码问题了,首先保证文件的编码是UTF-8
Step1: 文件编码设置
IDEA的setting里面如下配置:
然后确认下文件是不是UTF-8编码:
Step2: 编译器编码设置
现在大家大多使用maven,所以这里以maven为例说明。
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>{插件版本}</version>
<configuration>
<source>{java代码的语法版本}</source>
<target>{编译成class文件的版本}</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
也有说下面这样直接配就生效的,但是我没生效,大家可以试试,反正目的是一样的。
<properties>
<maven.compiler.encoding>UTF-8</maven.compiler.encoding>
</properties>
Step3: JVM输出(输入)编码配置
这一步通常不需要,因为是默认的。
java -jar app.jar -Dfile.encoding=UTF-8
Step4: 配置命令行输出编码
这个根据大家实际的工具来。一般系统的默认命令行工具的输出编码和系统的默认编码是一致的。所以大概率大家只要保证编译时的编码是对的就可以了。
大家可以从头一步一步来,不需要四步都做,到哪部成功了,后面就不需要了。
结束语
大家会发现,整个过程就是一开头百度出来的三种方法,我们可以猜测,之所以有人只用一种方法就解决了,是因为其他条件他是满足的。最后总结一下,盲目百度或许可以解决一时的问题,但是想要提高自己,还是需要深入学习深入思考。