JAVA与IDEA编码(乱码问题分析)全解析

本文深入解析JAVA与IDEA的编码问题,涵盖三个方面:代码源文件的编码与javac编译器一致性,JAVA运行时输出到控制台的编码与控制台解析编码的一致性,以及properties文件的编码问题。强调源文件编码与javac的匹配,JAVA程序输出编码的配置,以及IDEA中properties文件的透明ASCII转换设置对避免乱码的重要性。

对于整个编码问题的根本分析思路可以先参考我的另一篇博客:网页设计中文乱码原理剖析

本文从三个方面解析JAVA与IDEA的编码问题

1. 代码源文件的编码与javac编译器读取源文件使用的编码

2. java程序输出编码与显示控制台使用的编码

3.properties文件的编码问题

 

代码源文件的编码与javac编译器读取源文件使用的编码需一致

首先IDEA关于编码的设置主战场如下图:

Global Encoding作为IDE的全局编码,Project Encoding为System Default时生效,当Project Encoding不为System Default时,以Project Encoding为准。

经过一天的研究,发现IDEA这一块的功能还不是很完善成熟的,特别是一个Project中使用不同编码的*.java文件时,极其容易出现各种不确定的编码问题(目前用的是IDEA 2019.3,不知道以后会不会优化)。所以个人的建议是,一个Project的所有*.java最好是使用同一种编码,并且必须与此处的设置要一致,下方的特定文件编码列表只用于配置文件、属性文件或其他不含*.java的文件夹(最好是完全不要手工去编辑添加这个特定文件编码列表,IDEA会自动添加你的特定文件)。该处的设置主要是决定javac编译源文件时读取源文件用的编码,源文件与javac读取源文件所用的编码必须一致,否则,在java运行字节码文件时,无论怎么配置,都不大可能产生正确的输出,因为在编译阶段就出现了错误转码(源文件编码->java字节码文件内部表示编码)。

注意:改变Global Encoding或Project Encoding会影响新建文件的默认编码,但不会对已有的非纯ascii字符的源文件进行自动编码转换,这就意味着改变这个设置后,需要手动转换项目中编码不一致的源文件。

具体步骤:打开编码不一致的源文件,右下角选择新的编码,选择convert进行转换。

另外提一句,命令行指定javac读取源文件编码的方式如下:

javac -encoding GBK Test.java

也可以在IDEA如下位置配置:

一般情况下我们都是通过IDEA自动根据Global Encoding或Project Encoding去配置,无需手动添加。

 

JAVA运行时输出到控制台的编码与控制台的解析编码需一致

 在讨论这个问题前必须保证上面一点已经满足,即*.java被javac使用正确的编码去编译了,否则研究这一步毫无意义。

在第一步中,源程序中的字符串(特别是中文字符串)已经被正确转换为java字节码文件中的表示形式(机器无关,一般是Unicode的形式)。接下来的任务是以正确的编码输出到控制台,我们以控制台为研究对象,其输入是java程序的输出,输出是显示器(操作系统接口)。

JAVA程序的输出给控制台的编码可通过指定-Dfile.encoding参数配置,如:

java -Dfile.encoding=utf-8 Test

此处指定的编码无需与上文第一步中的一致,因为所有*.java中字符都已经被转化为一种中间表示形式存储在java字节码文件中(.class),输出到控制体可指定的编码是完全自由的。

对于控制台,要正确解析java程序输出的编码,就要选择一致的编码解析方式,在macos中,配置方式如下:

至此,当保证代码源文件的编码与javac编译器读取源文件使用的编码一致 和 JAVA运行时输出到控制台的编码与控制台的解析编码一致后,控制台输出的写在*.java中的字符信息就不应该会再显示乱码。

至于不是写在*.java中的信息,要保证不输出乱码,就要保证java程序中读取其他文件使用的编码与被读取文件所使用的编码要一致。详细可参考下面第三点作为例子。

另外,要表扬下IDEA自带的标准输出框,他会自动根据运行java程序时指定的(显式或隐式)-Dfile.encoding参数调节其解析的编码,所以只要*.java被使用正确的编码编译,就会正确输出写在*.java中的字符串。

properties文件的编码问题

这里主要讨论下图一中,这一块的具体配置与解析:

这里的选择编码与后面的可选项Transparent native-to-ascii conversion是二选一的。当勾选Transparent native-to-ascii conversion时,其实采用的编码是ISO 8859-1编码(这里要批评下IDEA这种容易令人困惑的设计),对于ISO 8859-1不能表示的标准字符,会采用转义字符+Unicode编码的形式去表示,如“中国”二字,使用ISO 8859-1应该表示为\u4E2D\u56FD,为了观看方便,IDEA会把这类表示转化为相应的字符显示,实际文件存储依然使用转义字符去表示。

在SpringBoot中,默认是以ISO 8859-1编码去读取*.porperties文件的,若使用utf-8或者GBK编码去编写porperties文件,就可能会导致出现乱码输出。因此,在开发SpringBoot应用时,可把这个Transparent native-to-ascii conversion勾上,在IDEA的帮助下,可同时兼顾查看方便与解决输入编码一致的问题。

注意,已采用utf-8或gbk编码的porperties文件(包含中文),勾选Transparent native-to-ascii conversion后会在下次编辑该文件时自动转换编码为ISO 8859-1。

 

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值