鐢辨湀瑕佸ソ濂藉涔犲ぉ澶╁悜涓?
����Ҫ�¨²�ѧϰ������
±æè¦å¥½å¥½å¦ä¹å¤©å¤©åä¸
ÓÉÔÂÒªºÃºÃѧϰÌìÌìÏòÉÏ
锟斤拷锟斤拷要锟矫猴拷
烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫
你没有看错,上面6行都是乱码。日常生活中,不论是文档处理还是程序设计,我们都会遇到类似的乱码,但这些乱码是怎么形成的?我们真的对乱码束手无策吗?
其实,类似“锟斤拷”的乱码在生活中经常出现,你甚至可以在一些大企业的官网或是软件界面见到他们......
你比如说甲骨文官方的Java文档......
以及随处可见的�
广大程序员间曾流传过一句打油诗:“手持两把锟斤拷,口中疾呼烫烫烫。”因为乱码问题一直以来非常常见。那么这些乱码的成因是什么呢?
从编码谈起
C语言课程中提到过,我们在计算机中能够看到的每个文字,在计算机处理的过程中,都要转成二进制,具体用哪些二进制数字表示哪个符号,这就需要编码。
我们非常熟悉的ASCLL码就是编码的一种,它解决了计算机显示英文字母的问题,ASCII 码一共规定了128个字符的编码,如空格SPACE是32(二进制00100000),数字0是48(二进制00110000)大写的字母A是65(二进制01000001)。
但是ASCII码在其他语言的情况下并不适用,比如汉字有10万个字符,所以有了其他的编码方式文件发出去是乱码,而世界的语言有许许多多种,一开始,各个国家与地区都是各自弄各自的编码。例如西欧的ISO-8859-1。
80年代我国大力发展计算机技术,可是出现的问题是,汉字显示不了。于是GB2312编码横空出世,囊括了六千多个常用汉字。
随着信息化的发展,GB2312似乎也不满足日常使用了,特别是生僻字。于是在90年代在GB2312的基础上扩展到两万多个汉字的字符编码GBK。
随着时代的发展,两万多个汉字似乎也是不够用,所以再往后,GB2312编码进化为GB18030编码,扩展到了七万多文字,还包含了少数少民族文字。
不同编码的弊端
类似地,其他语种也各自推出了自己的编码,但这个问题只是解决了本国语言和英文。当时面对另外一个场景,就傻眼了:一篇文献中,同时要引用中文、西欧文、拉丁文、小语种的文字呢?
前文已经告诉大家了:ÓÉÔÂÒªºÃºÃѧϰÌìÌìÏòÉÏ
这是早期出现的乱码,以这个为例,当我们以ISO8859-1的编码方式读取GBK编码的中文文件发出去是乱码,读出来的是这样。这相当于两组箱子,钥匙和锁是一模一样的,但是箱子里的东西不一样,那最终得到的东西还是不一样。
编码界大一统
于是在 20 世纪 80 年代末,大家坐在一起,决定讨论下这个事情,于是 Unicode 统一码联盟成立。并于 1991.10 发布了 Unicode 1.0, 到了 2020.3.10,发布到了 Unicode 13.0。今天 Unicode涵盖了包括了emoji在内的多国语言字符和特殊符号
Unicode 只是一个符号集,它只规定了符号的二进制代码,却没有规定这个二进制代码应该如何存储。如果 Unicode 统一规定,每个符号用三个或四个字节表示,那么每个英文字母前都必然有二到三个字节是0,这对于存储来说是极大的浪费。
所以在存储上,就有了Unicode的三种实现:UTF-8 UTF-16 UTF-32
新老交替出现的问题
如果我们想要用 Unicode 编码记录一些文本,特别是一些遗留的老字符集内的文本,但是这些字符在 Unicode 中可能并不存在。于是,Unicode会统一把这些字符记录为 U+FFFD 这个编码,它的UTF-8编码是0xEFBFBD。
U+FFFD这个编码显示出来长什么样子?
它长这样:�
也就是说,当Unicode发现了自己没收录而其他以前没统一的时候其他字符集收录的字时,它都会用�代替这个字。
在中文系统中,常见的字符编码是 GBK,这个时候,如果没有提前声明,默认按照 GBK编码显示。
我们知道,一个字节=两个二进制位,比如说0xEFBFBD中EF、BF、BD各自是一个字节。
而�两个连起来就是0xEFBFBDEFBFBD,而根据GBK编码的双字节要求,上面的6字节0xEFBFBDEFBFBD,就被拆成了3个2字节字符即0xEFBF,0xBDEF 0xBFBD,对应GBK编码里面就是:锟(0xEFBF),斤(0xBDEF),拷(0xBFBD)。
所以,�是我们以UTF-8的方式读取GBK编码的中文出现的。锟斤拷是我们以UTF-8方式读取GBK编码的中文,然后又用GBK的格式再次读取的时候出现的。
总而言之,这些乱码都是在不同编码的编写和读取之下出现的,这里列一个表,方便大家迅速地找到乱码的原因:
名称
示例
特点
产生原因
古文码
鐢辨湀瑕佸ソ濂藉涔犲
不认识的古文加杂日韩文
以GBK方式读取UTF-8编码的中文
口字码
����Ҫ�¨²�ѧϰ
大部分为小方块
以UTF-8的方式读取GBK编码的中文
符号码
ç±æè¦å¥½å¥½
大部分为各种符号
以UTF-8的方式读取GBK编码的中文
拼音码
ÓÉÔÂÒªºÃºÃѧÏ
大部分为头顶带有类似声调的字母
以ISO8859-1方式读取GBK编码的中文
问句码
长度为偶数时正确,长度为奇数时最后的字符变为问号
以GBK方式读取UTF-8编码的中文,又用UTF-8的格式再次读取
锟拷码
锟斤拷锟斤拷要锟矫猴拷
大部分为“锟斤拷”这几个字符
以UTF-8方式读取GBK编码的中文,又用GBK的格式再次读取
总之,用什么 [编码规则] 保存为何种形式的二进制段,就用同样的[编码规则]来读取。自然就不会出现乱码了。
烫烫烫是电脑过热?
至于“烫烫烫”,肯定是电脑CPU的过热造成的转码紊乱。
这个乱码会在Visual Studio中出现,Visual Studio会把没有赋值的变量或者内存地址全部填成0xCC,而两个0xCC组成0xCCCC转换成中文就是“烫”了。所以,发现“烫烫烫”刷屏,不是电脑过热报警,而是你的变量没有初始化就使用了。
小结
了解了这些原理,相信你未来在遇到中文的编码问题的时候,可以做到“手中有粮,心中不慌”了。
知其然,还要知其所以然,我们才能在问题发生时有效处理,淡然处之而不至于手忙脚乱。
往期精彩
图文:魏子奇
版权声明
本文仅代表作者观点。
本文系作者授权发表,未经许可,不得转载。
发表评论