2017-10-10 都市传说: "部分"中文出现乱码

探讨了在中文Windows环境下,部分中文出现乱码的原因,尤其是在Java项目中从UTF8到GBK编码转换时出现的问题。文章详细分析了编码转换过程中的错误处理机制,并提供了具体的示例,解释了为何会出现“部分”乱码的现象。

知乎原链, 作者亦本人

事情起源于项目另一开发者在中文Windows下构建时遇到的部分中文出现乱码问题.

当时很不解的是, 为什么会只有部分出现乱码. 第一感觉是, 如果编码转换不正确, 要么全乱码, 要么全正确. 为何会"部分"出现乱码.

初步分析在此. 简单说, 就是在转码过程中, Java会把某些它不认识的部分直接用某个值代替. 至于为何不默认保留原数据, 是个好的考古研究课题.

示例如下(除了"开始检", 其他都乱码了):

编码原字1原字2原字3原字4原字5原字6
原字
UTF8表示e5 bc 80e5 a7 8be6 a3 80e6 9f a5e2 80 a6e2 80 a6
转为GBK后e5 bc 3fe5 a7 8be6 a3 80e6 9f a5e2 3f a6e2 3f 3f
转回UTF8�?�?��??

网上很多资源提到字符数是奇数会有问题, 这是没错. 但实际上即使偶数也可能会有问题. 上面的转换过程中, 80不是合法GBK字符, 就被替换成3f. 而替换过后再转回UTF8当然就挂了.

这个问题里的插件就是把输出字符串指定编码成了UTF8格式的数据, 但输出/解码时又用了系统默认的编码格式(GBK). 详见 GBK<->UTF8 互转问题: Maven checkstyle输出乱码 · Issue #26 · program-in-chinese/overview, zh-cn ,,,, cmd gbk encode · Issue #3569 · checkstyle/checkstyle.

个人觉得这种转码问题是除了亚洲/非洲之外的开发者很容易忽视的. UTF8的字符除了亚洲(包括中日韩)和非洲语言的字符用三字节数据表示外, 其他多数语言的字符都是用单字节或双字节. 来源). 这些UTF8中三字节的字符和GBK之类的双字节码转码时会更容易出问题.

在调查过程中, 还发现了其他一些类似疑问, 比如UTF-8编码,部分中文正常,部分为乱码的问题?-优快云论坛.

直觉是也是类似问题, 但想用编码互转的方式重现未果, 参考上面的例子试了几种2次转码, 都没有重现. JDBC连接MySQL抛出异常信息乱码 - insist的专栏 - 优快云博客提到了CP1252编码, 又经过几次尝试, 才试出了这个过程: "utf-8"->"windows-1252"->"iso-8859-1"->"utf-8".

阶段总结一下, 乱码问题的缘由都是编码互转. 全部乱码, 部分乱码都可能. 随着国外代码库/软件的编码方式更多地使用UTF8, 类似第二个问题的可能会变少, 但类似第一个的UTF8<->GBK互转的问题也许会存在很长一段时间.

转载于:https://www.cnblogs.com/program-in-chinese/p/partial_encoding_issue_for_Chinese_text.html

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值