大神解惑|为什么要用UTF-8

小白在学习 Python 中的“字符串”这个基本概念时,问了大神这样一个问题:既然 Python 内部的字符串都是使用 Unicode 来编码的,那干嘛还要在存储和传输的时候转成 UTF-8 呢?这样转来转去的多麻烦?

说实话,回答小白的问题,通常比回答大神的问题要难。因为他们总是问一些不着边际的问题。好在伟大的互联网时代,没有什么事情不可以通过在网上搜集信息,整理分析之后给出一个相对满意的回答的。

小白提出这个问题,主要是源于网上教程中一个错误的解释:Unicode标准也在不断发展,但最常用的是用两个字节表示一个字符(如果要用到非常偏僻的字符,就需要4个字节)。于是,小白就认为,既然2个字节可以搞定,干嘛还搞成 UTF-8,因为那样可能需要 3 个字节或者更多来表示一个字。这里的错误是什么呢?就是混淆了“标准”和“实现”。好吧,小白肯定又要晕了。

先来举一个现实中的例子:现在我们使用的长度单位是“米”。这就是一个标准。这个标准怎么定义的呢?在国际计量学会有几个标准“米”容器,那个东西的长度,就被定义成一个标准的“米”。但不会有谁真的跑去用那个标准容器。我们都是以那个标准容器为样板,生产自己的尺,来测量东西。这个尺就是“米”这个标准的一种实现。我们可以做一根硬的木尺,也可以是软的卷尺,还可以是使用激光测距的光尺。不管怎么说,只要这个尺量出来的“米”和标准容器量出来的“米”是一样的,那就可以了。

那么 Unicode 是怎么回事呢?Unicode 做为一个国际标准,其实只是定义了每个字符对应的一个数字(实际上 Unicode 包含很多复杂的内容,这里只说最简单的部分),比如 20031 这个数字就代表“中”这个字,25991 代表“文”这个字。但其实 Unicode 并没有说你要怎么保存一个字。

现在大家都知道,电脑里存信息,通常使用的单位叫:字节。比如我们说一首歌下载需要 3MB 的流量,翻译成“人话”,就是需要传输 3 百万字节的信息。一个字节能表示的数字非常的少,只能表示 0 - 255 这 256 个数。那如果我们需要表示超过 255 的数字要怎么办?那当然就是用多个字节。比如两个字节就可以表示 0 - 65535 这 65536 个数了。那我要表示负数怎么办?最笨的办法就是用3个字节嘛,用一个字节来表示正负,剩下的字节来表示数字。当然小白肯定会说:正负就两个状态,需要一个字节,那多浪费!于是,有就了各种不使用3个字节也能表示正负数的方法。这部分内容,任何一本“计算机原理”的书里都会讲到。什么符号位啊,补码啊……

讲这么一堆关于怎么表示一个数字的问题干什么呢?和这里说的 Unicode 和 UTF-8 有什么关系呢?当然有关系!这里大神要说的意思就是:同样一个数,你可以选不同的方式来表示它(比如刚才说的用3个字节来表示正负数,或者使用符号位来表示正负数)。选用什么方案,就是对 Unicode 的一种编码方法,也就是我们刚才说的“实现”。为什么前面提到的教程作者会说 Unicode 通常是两个字节呢?因为在 Unicode 早期,设计 Unicode 的人学识有限。他们在考查了世界上主要的文字之后,感觉用2个字节也就是最多 65536 个字符应该够用了。对应于一种 2 字节的编码方案叫 UCS2。后来做着做着,发现不对了,2个字节不够用了(现在 Unicode 包含了 12万 8 千个字符),又扩展到4个字节(因为计算机使用二进制的原因,3个字节在读写的时候很没效率,所以都是2的倍数来扩展的),对应于一种编码方案叫 UCS4。而对于我们来说,常用的中文字都在 65535 以下,所以通常 UCS2 就能表示常用的 6000 多个汉字了。这里说的 UCS2 和 UCS4 都是 Unicode 的“实现”,或者叫编码方案。虽然,因为 UCS2 不能覆盖全部的 Unicode 字符集,已经被标为“废弃”了,但不要被他们骗了,一个已经使用了很久的技术,想废弃是非常难的。

UCS2 和 UCS4 都是固定编码长度的方案。也就是说不管是什么字符,都使用 2 个字节或者 4 个字节来表示。对于我们来说,这并不是什么问题,但问题出在:这个世界上最流行的语言不是汉语,而是英语(中国人表示不服!汉语是世界上使用人数最多的语言)。虽然把每个英语字母都使用两个字节来表示也不是什么大的问题,可是,在遥远的计算机启蒙时代,无论是硬盘的大小还是网络的速度,都非常的有限,如果不对传输的内容进行压缩和限制,那成本是非常高的。于是就有了 UTF-8。

和 UCS2 这样的固定编码长度的方案不同的的是,UTF-8 并不是固定长度的。最短的 UTF-8 字符只需要使用 1 个字节。最长是 5 个字节。最长那 5 个字节能表示的数字,相当于用 4 个连续字节用来表示正负数,里面正数的个数,大概有20多亿,具体是多少,其实也不重要。看起来,多用了一个字节,还没有原来表示的数字多,好像很浪费,但这里的目的是:最常用的英文字母,使用最少的字节,不常用的,反正也不常用,多两个字节没关系。(这里请不要批判帝国主义霸权。不是人家想把英文搞这么短,是我们的中文想搞短也做不到……)

说回 Python。在 Python 3.3 版之后,对内部的 str 表示做了一些改进。教程里说:Python 内部使用 Unicode 来表示字符串,而在保存到硬盘或者发送到网上,需要转成 UTF-8。这个说法其实不够准确。在 Python 内部(不同的版本可能不同,大神在这里引用的是 Python 3 的文档),是使用 UCS 的各种版本来表示字符串的。比如说,对整个字符串做一次扫描,发现所有的字符都小于 255,那么就使用 UCS1,也就是一个字节的编码方案;如果发现有大于 255 的字符,但又都小于 65535,那么就使用 UCS2。当然,如果发现有奇怪的字符,那就只能使用 UCS4 了。为什么在内部要使用 UCS 呢?怎么不继续使用 UTF-8,那样不就不用转换了吗?(小白总是想省事)这个就涉及到 UTF-8 的一个缺点:计算字符串长度和查找子字符串非常没效率。在使用 UCS2 的时候,要想知道这个字符串有多长,只要看一下它占了几个字节,然后除个 2 就可以了,而 UTF-8 的话,就需要一个字符一个字符的数出来。在做子字符串搜索的时候,因为不知道下一个字符占几个字节,所以那些高效的搜索算法也都不灵了(小白:算法是啥?)。基于这两个原因,只好做一个转换:在保存到硬盘或网络传输的时候,使用一种压缩的方案,使得传输或保存需要的字节数最少;而在内部进行处理的时候,则使用效率更高的 UCS 方案。

PS:大神非常爽的讲完之后,小白似懂非懂的走开了……

参考资料:

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,029评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,395评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,570评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,535评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,650评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,850评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,006评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,747评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,207评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,536评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,683评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,342评论 4 330
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,964评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,772评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,004评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,401评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,566评论 2 349

推荐阅读更多精彩内容

  • 字符集和编码简介 在编程中常常可以见到各种字符集和编码,包括ASCII,MBCS,Unicode等字符集。确切的说...
    兰山小亭阅读 8,464评论 0 13
  • 可以看我的博客 lmwen.top 或者订阅我的公众号 简介有稍微接触python的人就会知道,python中...
    ayuLiao阅读 3,097评论 1 5
  • 清晨的第一抹朝阳染红海面天际 从远处传来的孤寺撞钟声 回荡整个山谷 惊起了树林中栖息的鸿雁 木鱼打鸣声中 扫地僧人...
    颍阿阅读 294评论 4 16
  • 你最近的状态怎么样呀?浑浑噩噩,不知所措。似乎这样消极的回答是我在与用户进行交流沟通时听到的最多的。然而一个人真的...
    王二道阅读 408评论 0 0
  • ​无论友情还是爱情,你有被人坚定的选择过吗? 我相信每个人骨子里其实都是自私的,都希望自己拥有的爱是独一无二的,是...
    米未阅读 4,239评论 6 9