1992年9月1日,星期三下午,贝尔实验室。RobPike(Go语言的发明者之一)正在忙于操作系统Plan9,这是Unix之后的一个大项目,即将完成。就在这时,他突然接到了一个电话。(年轻帅气的RobPike)电话是IBM的一个人打来的,他正在奥斯汀参加X/Open委员会会议,想请RobPike和KenThomson(Unix的发明者)审查他们设计的一个Unicode代码。RobPike知道X/OpenCommittee主要负责制定Unix的标准规范,以提高应用程序在不同Unix变体上的可移植性。显然,这次会议的主题是:Coding!RobPike想到了Plan9,他正在做的操作系统,为了支持英语、中文、韩语、日语、阿拉伯语等世界各国的语言……Plan9当然要用Unicode。(为什么这个产品和Go的吉祥物长得那么像?)大家都知道,Unicode只是规定了每个字符应该使用什么编码,并没有规定如何存储。当时,Plan9采用了一种叫做ISO10646UTF的编码,但是这种编码真的很糟糕,据RobPike说:我们讨厌这种编码。Rob和Ken立刻意识到:机会来了!Rob:我们经验丰富,为什么不设计一个真正好用的Unicode存储标准呢?Ken:同意,我们自己设计,把标准的推进交给X/Open委员会。两人向IBM的人表达了这个想法并得到了支持,条件是:一定要快,快设计,快实现。因为下周一就要投票了!快速、高质量地完成工作对于有才华的程序员来说是小菜一碟。两人去餐厅慢慢吃。吃饭的时候,Ken和Rob设计了基本方案,就是大名鼎鼎的UTF-8。回到贝尔实验室后,他们写下了这个想法的大纲,并将其发送给了X/Open委员会。委员会的答复是:这比我们设计的版本要好得多。你什么时候能够实施它?Rob和Ken拍了拍Chest说:别着急,下周一肯定会有一个完整的可操作的实现。那天晚上(星期三),两个人撸起袖子干活,Ken做打包解包代码,Rob去折腾C和图形库相关的东西。星期四,所有的代码都完成了,Plan9操作系统上的文本文件被转换为UTF-8。周五,Plan9操作系统已经在UTF-8上运行。居然只用了不到三天!这三天的工作成果最终主导了整个互联网的编码标准。统计显示,现在96.8%的网站都在使用UTF-8。2故事讲完了,我们来看看UTF-8为什么能流行起来。前面说了,Unicode只是一个字符集,规定了每个字符的二进制编码,比如“code”,对应的Unicode是7801,二进制数是111100000000001,需要两个字节来保存。如果它表示其他更大范围的字符,可能需要3个字节或4个字节,甚至更多。当计算机面对这两个字节的字节流时,就会产生一个严重的问题:计算机如何知道这两个字节是否代表一个字符?还是两个字?大家都知道英文字母表用一个字节Saving就够了。如果Unicode规定每个英文字符要用两三个字节保存,那么每个英文字母前面都要加上0,文本文件就会大两到三倍。这是一种巨大的浪费,当然不是。Rob和Ken设计的UTF-8更聪明。看这张表:把Unicode转成UTF-8很简单。比如汉字“码”,Unicode是7801,二进制是1111000000000017810,对应上图中数字1的三行,把二进制从右往左填入对应的“模板”即可,如果没有足够的零填充,更多细节将不展开,关键是看UTF-8的好处。31、兼容ASCII,表格第一行设置为ASCII。多字节编码每个字节的最高位始终为1,而ASCII字符编码最高位为0,从根本上杜绝了编码冲突。2.第一个字节表示后续的长度。程序在面对字节流时,只需要读取第一个字节开头的1的个数,就可以知道这个字符的长度。解码非常方便。.3、请仔细观察前缀码。UTF-8中没有合法字符是其他字符的前缀。这样带来一个好处:支持程序快速跳过有问题的字节,然后正常解码。假设有“码”和“农”两个汉字,对应的UTF-8编码为E7A081(码)和E5869C(农)。但是在网络传输中丢失了部分数据,变成了E781E5869C(也就是“代码”的A0丢了)。现在程序先读取E7,二进制值为11100111,知道这个字符应该是3个字节,后面的两个字节都应该以10开头,所以还要再读取两个字节,因为字节A0丢了,程序读取81和E5。程序发现:81(二进制10000001)是符合规范的E5(二进制11100101)的前两位,不是10,应该是另一个字符的开始。所以程序判断缺少了一些字符,可以舍弃刚刚读取的E781,然后从E5开始读取,E5869C,最后显示“农”字。是不是很聪明?
