• 【UTF-8编码透析】神奇的“联通”乱码现象


    小伙伴们大家好,我是低调儒雅的Steven老师,作为开发人员,或许听说过“神奇的联通乱码现象”。没有听说也没有关系,那什么是“联通乱码现象”?到底是什么原因造成这个现象产生呢?

    本文帮你彻底答疑解惑,当你理解“联通乱码现象”的根源后,其实也就真正加深了对中文乱码的解决之道。

    有个很著名的奇怪现象:当你在 windows系统 的记事本里新建一个空白文件,在文件里输入"联通"两个字之后保存,关闭文件后再双击打开。观察到什么了吗?输入“力挺联通”,保存后再双击打开,又会如何呢? 

    输入“联通”两个字的时候:             

    输入文字时是正常的

    保存并关闭文件,双击打开后的结果:     

    双击打开记事本,显示乱码

    输入“力挺联通”四个字的时候:          

    输入文字时是正常的

    保存并关闭文件,双击打开后的结果:          

    双击打开记事本,显示乱码

    你会发现,明明输入的是正确的文字,但是关闭后再双击打开文件,发现文字消失,取而代之的是几个乱码!为什么会这样呢?

    大家知道,记事本是微软的产品。莫非联通得罪了微软?

    为了能透彻理解这个奇怪的现象,一定要透彻理解字符编码,尤其是UTF-8编码格式。

    接下来让我们来分析一下计算机对UTF-8文件的解码过程。掌握了UTF-8文件的解码过程,那么就具有了解释“奇怪的联通现象”的技术基础了。

    好吧!说干就干。

    有一个UTF-8编码的文本,文本内容为:“a0一” 。

    分别是英文字母“a”,数字“0”,中文汉字“一”。接下来我们来分析一下这个文件,计算机是如何识别的吧。

    一.获取十六进制编码的内容

    在这里介绍一个软件:UltraEdit文本编辑器。用这个软件,可以查看文本的十六进制代码。

     

            

    建议安装软件UltraEdit 

    在UltraEdit编辑器中输入文本“a0一”

    文本“a0一”的16进制

    1、在文本编辑区输入内容

    2、选择字符编码格式

    3、点击“16进制编辑”按钮,查看文本内容的16进制

    所以,获取到“a0一”的16进制为:

                61    30    E4    B8    80

    二.将16进制的内容转成二进制

    进制转化可以通过在线进制转换工具实现      

    通过在线工具进行进制转换

    1、输入网址

    2、选择进制

    3、在文本框输入内容

    4、点击“转换”按钮

    5、查看对应进制的内容

    所以16进制:61    30    E4    B8    80

    转成二进制后如下:(不足8位长度的在数字前端补0)

    01100001 

    00110000

    11100100

    10111000

    10000000

    每8个数字代表一个字节,所以能看出该文本共有五个字节。但是到底哪几个字节是一个字符单元呢?计算机是如何分组的呢?

    因为该文件保存的格式是UTF-8编码格式,我们来回顾一下UTF-8编码的特点:

    1、UTF-8编码是可变字节编码。所以每8个字节并不一定就是一个字符。有可能8个字节是一个字符,有可能16字节是一个字符,有可能24字节是一个字符。

    2、文本读取是一个字节一个字节的来读取,根据字节开头的标志位来识别,从而能确定到底几个字节是一个字符单元。

    3、UTF-8编码规则中,原Unicode前128个字符是单字节编码(实体编号在127以内),编号在128至2047的是双字节编码(2的11次方=2048),编号在2048之后就是三字节编码。

    (1)如果字节的第一位是0,则说明这个字节是单字节;

    (2)如果第一个字节的前3位是110,第2个字节的前2位是10,符合这个规律的连续相连的两个字节就代表一个双字节的字符;

    (3)如果第1个字节的前4位是1110,第2个字节的前2位是10,第3个字节的前2位是10,符合这个规律的连续相连的三个字节就代表一个三字节的字符。

    UTF-8编码的二进制格式

    三.根据UTF-8编码规则以上二进制内容被分为三个组:

    01100001     第一个字符

    00110000     第二个字符

    11100100      以下三个字节是一个中文字符,符合1110xxxx 10xxxxxx 10xxxxxx的格式

    10111000

    10000000

    四.重新计算,得出对应Unicode字符集的二进制编码

    Unicode字符集是双字节编码,所以每16位数字代表一个字符。

    删除标记位上的数字,将剩余的二进制数字合在一起,不足16位的,在数字前补足0。根据这个规则,以上二进制数字就变成了以下三组二进制的数字。

    00000000  01100001      第一个字符

    00000000  00110000      第二个字符

    01001110  00000000       第三个字符 

    五.将上述三组二进制数字转成10进制

    进制转化可以通过在线进制转换工具实现。  

    (二进制转10进制时,要将0或1之间的空格去除,再通过工具进行转换。)

    上述二进制对应的十进制数字为:

    97

    48

    19968

    六.通过10进制反查在Unicode字符集中它们对应的字符

    97、48、19968其实就是Unicode字符集中字符的索引下标。Unicode字符集中索引为97的符号是哪个呢?其实熟悉ASCII表的同学都知道,是小写字母“a”。不熟悉的话也没有关系,我们可以通过以下方式来查看。

    新建一个html文件,在文件中输入:

    a0一

    &#实体编号;——这种格式是html的实体编码格式。写好后保存关闭文件,然后双击打开,我们可以在浏览器中看到显示内容:a0一 

    展示html文件的内容

    掌握了计算机对UTF-8文件的解码过程,接下来我们来解释奇怪的“联通”乱码问题吧

    当新建一个文本文件时,记事本的编码默认是ANSI,在ANSI编码格式的文件里输入汉字,那么实际就是GB2312编码格式。在这种编码下,"联通"的十六进制编码是:C1 AA CD A8       

       

    在UltraEdit编辑器中输入文字“联通”

    “联通”两个字的16进制

    将C1 AA CD A8转成二进制后:

    11000001

    10101010

    11001101

    10101000  

    UTF-8文字的二进制格式

    大家有没有发现,这个GB2312文件的二进制数字格式竟然与UTF-8的二进制格式巧合地撞车了。

    虽然保存的是GB2312编码,但是“联通”这两个字的二进制数字正好和UTF-8的格式完全吻合,所以记事本就把这个文件当做UTF-8编码格式了,自然就以UTF-8编码方式来打开并解码了。根据UTF-8编码规则,以上二进制内容被分为两个组,内容为:

    0000000001101010

    0000001101101000

    转为10进制后为:106和872,Unicode字符集中第一个中文字“一”,序列号是19968,所以106和872这明显不是中文。

    奇怪的联通现象,出现乱码的主要原因是:GB2312编码与UTF-8编码产生了编码冲撞,导致编码误解,从而触发了错误的文件打开方式所引起。

    如果输入中文"爱联通",保存文件后关闭,当再次打开,则不会出现乱码问题。因为中文“爱”在编码表中对应的二进制数据不符合UTF-8的格式,所以记事本不会误解该文件是UTF-8编码格式,就会用默认的GB2312编码来解码,自然就不会出现乱码。其实在“联通”两个字前或后多输入几个字,就不会出现这样的巧合了。

    那么输入“力挺联通”四个字是不是就不会这么巧合而乱码了呢?

    非常奇妙的是输入“力挺联通”,还会出现乱码。原因是“力挺”这两个字的GB2312二进制编码也恰好与UTF-8吻合。

    整个文件里的四个字都是符合UTF-8编码格式的,自然就会被误解为UTF-8编码的文件,那么双击打开时就会采用UTF-8编码方式来解码。

    巧吧!       

        

    在UltraEdit编辑器中输入“力挺”

    更改编码格式为GB2312

    “力挺”两个字的16进制是:C1 A6 CD A6

    C1 A6 CD A6

    转成二进制后:

    11000001

    10100110

    11001101

    10100110

    这也符合UTF-8编码的格式。

    总之,只要GB2312文本的二进制编码不与UTF-8格式完全吻合,就不会被误解是UTF-8文件,也就不会因为误解而采用错误的编码方式来解码了。

    其实换一种文本编辑器来打开,乱码问题就可以避免。如果没有专业的文本编辑器,甚至使用浏览器来打开,也能正常显示出中文内容。本文采用EditPlus来打开该文件。

    当采用正确的编码格式来打开,原本被认为是乱码的文件就正常显示了。

           

    例如采用EditPlus文本编辑器来打开 

    直接双击用记事本打开,显示为乱码的文件,当采用EditPlus打开后就显示正常的文字

    *威哥Java学习交流Q群:691533824
    加群备注:CSDN推荐

  • 相关阅读:
    酒店管理系统小程序的设计
    Windows下载最新谷歌浏览器
    Phoenix创建Hbase二级索引_尚硅谷大数据培训
    code-push热部署开发者端
    Spark SQL函数
    java计算机毕业设计ssm基金分析系统的设计与实现(源码+系统+mysql数据库+Lw文档)
    Visual Studio Code 常见的配置、常用好用插件以及【vsCode 开发相应项目推荐安装的插件】
    浅谈Foxmail邮件迁移
    BUUCTF 被偷走的文件 1
    图论算法
  • 原文地址:https://blog.csdn.net/finally_vince/article/details/126034969