关于使用gradle编译java导致中文乱码的分析以及解决(完美且分析了所有情况)

之前的文章分析了一些关于gradle乱码的原因,其实说来还是各种隐藏的编码问题导致的,但是之前那篇文章是一边查一遍写的,看起来很累,这里直接整理一下java项目从编译到输出会遇到的所有编码不一致的情况,统一这些所有情况就解决了编码问题

最常见原因,Windows系统编码

windows有两个东西来控制编码,一套老的叫活动代码页,一套新的叫系统编码,如果你在老系统上,我也不确定老是多老,也许是在区域设置中有启用utf8支持就算是新系统
区域编码
如果你的电脑有这个使用utf8提供全球支持,那么电脑里一定有两套编码控制,新程序一般都会使用这个系统编码,一般是GBK,如果你的电脑勾上了这个utf8全球支持选项,你的系统编码就会变成UTF-8

而另一套老的编码控制叫活动代码页,打开你的cmd,记住是cmd,而不是powershell,且不要从windows的新终端程序打开,也就是这个
在这里插入图片描述
而是直接打开一个cmd窗口,然后输出chcp,你就能看见当前使用的活动代码页,由于我的电脑已经勾上了utf8全球支持,所以所有默认活动代码页会被统一成65001,也就是utf8,而你们应该是936,也就是gbk
在这里插入图片描述
如果你直接在这里执行java程序,那么你当前的代码活动页会影响java程序的输出编码,也就是System.out的编码
在这里插入图片描述
你在utf8的活动代码页下启动,它就是utf8,你在gbk下启动它就是gbk
也就是说java程序的输出是跟着启动终端的活动代码页走的,而活动代码页会被系统编码统一设置,层次关系是
系统编码(最高)->终端活动代码页

文本格式本身

idea编码
只要idea右下角的编码显示为utf8就代表文件的编码是没问题的,不过这里有个坑,idea支持编码的转换,但是这个转换有点慢,有时候你从gbk转换到utf8之后等一等再运行,我之前发现点快了结果依旧是乱码,等一等就好了

Java编译器选项

java编译器有一个javac -encoding=utf8选项来指定读取java文件的编码格式,由于一般不采用手动编译,而是交给gradle或者maven这种管理工具,所以需要配置这些工具在编译java时的选项,在gradle中的配置如下
在这里插入图片描述
这里我只放kotlin版本的了,groovy的最好找就不放了,也许以后会补

Java虚拟机读取文件的编码

java虚拟机在启动时会有一个参数控制jvm的编码,jvm会用这个编码去读取文件,这个编码会影响Charset.defaultCharset()这个方法的编码,这个参数会影响jvm读取文件时采用的默认编码,指定这个编码的选项是java -Dfile.encoding=utf8,这个选项也是许多教程里面讲的解决方法之一,可惜只配置这个很难解释其他情况出现的乱码,这个选项只是为了控制在读取以utf8编码选项编译完成之后的class文件的读取也是以utf8编码,如果你编译的编码和文件的编码就不是utf8,那么即使正常输出也是歪打正着
这个编码的设置在gradle内似乎没有提供选项配置,但是可以通过两种方式去控制

  1. 设置idea的jvm的编码
  2. 修改gradle脚本的启动参数

首先讲第一个,在idea内使用gradle时会把当前jvm的配置传递给gradle的jvm,也就是说如果idea的vmoptions文件配置了-Dfile.encoding=utf8时,idea内启动的gradle也会继承这个编码,这样就实现了控制gradle的jvm编码

第二个,这种方法下不能再使用idea运行,因为这样也可能导致乱码,可以修改gradlew的脚本来在终端启动一个以utf8为编码的gradle进程,记住我修改的这个文件叫gradlew.bat,这是windows下的gradle脚本,另一个没有bat后缀的是linux下的,不要看错了
在这里插入图片描述
linux的脚本也类似,这里不贴了

idea设置选项里提供的编码

在这里插入图片描述
在idea这个界面可以设置一个很神奇的环境变量,当你设置了全局utf8之后,idea会统一文件,以及idea本身终端的编码,记住是idea本身那个输出窗口的编码,但是由于gradle和idea是分离的,所以idea的这个全局utf8无法影响到gradle,只限于idea内文件的编码,以及idea的输出窗口的编码,同样也无法影响idea进程所在jvm的默认编码,这个设置功能很有限

输出终端的编码

在idea这节我们已经说了,在设置->编码里面可以修改输出的编码,接下来主要讲的是powershell
由于我们已经知道了java会通过启动时终端的代码活动页来控制输出编码,以确保在展示输出时不会乱码,这里cmd没什么问题,接收到java程序的输出就用当前代码活动页去老老实实展示,但是powershell就有意思了,假设此时powershell的代码活动页为65001,也就是utf8,那么启动的java程序也会输出utf8编码格式的内容是吧,但是在中文系统中,powershell默认的展示编码是系统编码,如果你没有打开全球utf8支持,中文系统下系统编码就是gbk,也就是说powershell会以utf8环境运行java程序,并且java程序输出了utf8,powershell再拿去用gbk编码展示,那能不乱码吗,要解决这个问题,要么不修改代码活动页,执行java时会以gbk输出,可是我们的class文件内的中文是utf8啊,还好贴心的java会帮我们做一个转换,所以最终输出是正常的,要么修改powershell的展示编码,也就是这样
在这里插入图片描述
你也可以只打出$OutputEncoding来查看当前输出编码

最后总结

如果你在使用idea+gradle,那么你需要修改idea全局编码(为了控制文件的编码以及输出窗口的编码),idea的jvm编码,也就是-Dfile.encoding=utf8(为了确保gradle的jvm会以utf8读取你的文件,如果已经打开区域里的utf8支持就不用了),以及配置gradle的编译选项
tasks.withType(JavaCompile::class.java){
options.encoding=“UTF-8”
}
这样整个程序的编码就统一了,但是记住,这只限于idea+gradle,如果你要在终端使用gradle或者运行编译好的程序,也就是
使用终端+gradle
,那么就得配置好gradle启动时的jvm配置,终端的代码活动页,如果是cmd就只需要配置这一个,如果是powershell还需要配置输出编码,如果你开启了区域里面的启用utf8支持,那么就不需要修改代码活动页而只需要修改powershell的输出编码了(不过其他老程序可能乱码)
如果你在windows下遇到了乱码问题,可以检查以上所有地方以确保编码统一

  • 16
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值