编码: 一个隐藏了30多年的bug,Windows含蓄说过某通不行?( 二 )


区位编码
但是只是简体中文字符的编码标准,在台湾地区的繁体字用的是BIG5字符集,在日本则有S-JIS 、 等字符集,这样同一个数值表示的含义在不同的字符集里表示的实际字符就会不一样 。后来为了改变这个混乱的局面,ISO组织搞了个、统一码联盟搞了个字符集,后来他们俩讨论决定只做一样的字符集,二者保持同步,意图将全世界的所有字符放在一个统一的字符集里面,每个字符都有自己唯一的“身份” 。的出现为世间的编码灾难带来了曙光,但是”存在即合理”,历史存在的字符集已经存在了,各种应用程序为了向前兼容,仍然要支持老的字符编码标准 。比如在简体中文系统里面,虽说新的应用程序已经支持字符集,但是依然在简体中文世界里大行其道 。
桔子菌看着橙子妹欲言又止的样子,赶紧主动收拢了话题,没有扯更远的GBK,之类的汉字字符集了,况且也能说明问题了 。到现在背景也介绍的差不多了,该来点实际的东西了 。
再回到刚才的“联通”问题,用自带的记事本保存的时候,默认保存的方式是“ANSI”方式(中文操作系统里实际上用的是编码标准,只是称呼上叫ANSI),点击记事本的文件菜单下的另存为,可以看到能选择不同的编码方式保存:
记事本多种保存格式
继续按照剩下的、 big 、UTF-8 三种编码方式另存为三个文件 。再双击打开文件的时候这3个文件都能正常显示”联通”2个字符了 。这中间发生了什么神奇的事情?

编码: 一个隐藏了30多年的bug,Windows含蓄说过某通不行?

文章插图
好了,到了该祭出神器的时候了,软件是一款强大的二进制分析工具,不但可以分析磁盘启动区、修复文件,还可以用来查看文件的二进制内容,我们用软件把前面保存的4种格式的文件打开看看 。
解析文件的二进制数据
第一部分是用ANSI方式存储的文件,打开后显示存储的数值是C1,AA,CD,A8,查看下”联”、”通”的编码,其数值分别为C1AA,CDA8,说明用ANSI方式保存就是用的编码方式存储的,下面2张图是的码表截图 。
“联”字编码
“通”字编码
再继续看下”联通”的编码数值是多少,找一个“ 编码”这类的工具网站,输入“联通”字符查询编码:
“联通”的编码与UTF=8编码
【编码: 一个隐藏了30多年的bug,Windows含蓄说过某通不行?】从上面的转换可以看到,右边橙色框是数值,”联”、”通”分别对应了和的编码值,正好和按照 big 方式保存文件的第三个字节开始的内容是一样的 。而按照方式(实际是 )保存的文件内容和前者的顺序正好是”交替”存储的 。关于big 和 的区别,简单点说big 就是高位字节的数据存储在低地址的模式,则正好相反 。用打开文件看到的越往前是低地址,越往后是高地址,在big 文件中可以看到”联”的高字节内容0x80排在前面低地址,低字节内容0x54排在后面高地址,而 正好相反 。这也体现在最开始的2个字节上,big 的是FE和FF,而 是FF和FE 。
从的2种编码方式看,前面2个字节(BOM、字节序)并不是真正意义上的字符内容,它的作用相当于告诉应用程序这是采用方式编码的文本文件,并且表明后面的字节顺序用的是 big还是。这一点和图片文件类似了,用了些冗余的字节表明其编码方式,这样文本程序打开这种编码方式的文件时,就能正常识别编码方式并按照正确的姿势打开文件了 。还记得在前面提到编码中没有0xFF的数值么,这里正好可以用来约定编码方式 。
再来看下UTF-8编码方式,UTF-8并不是一种字符集,而是实现字符集的一种编码方式,实际上表示的还是字符集,可以形象地理解为字符集本身是一种“信源”编码,而UTF-8则是一种“信道”编码 。规定的字符集和UTF-8编码的对应关系是下图这样的,编码范围分为4个,每个范围内的字符对应了一种编码方式,比如在 0000~ 007F之间的值需要1个字节表示,这样对于ASCII字符就只需要1个字节表示,做到了和ASCII字符集的兼容,而大多的汉字字符落在第3行的 0800~ FFFF范围内,需要用3个字节表示: