专栏首页Web行业观察这难道是UTF-8字符编码的设计缺陷?

这难道是UTF-8字符编码的设计缺陷?

  • 信息论进阶:聊聊UTF-8的信息熵

UTF-8都知道是啥,所有人都在用它来存储和传输文本。鄙人闲来无事研究了一下utf8的规格,发现它并没有想象中的那样完美。

问题起源于StackOverflow上的一位网友提问:

地址:https://stackoverflow.com/questions/53009692/utf-8-encoding-why-prefix-10

网友提到,utf8本是一个可变长度字符编码,这意味着utf8的设计目标是为了节省流量,给使用频率高的字符以短字节,给“冷门”的字符以长字节,就像哈夫曼编码一样。但后来我发现了一个惊人的事实:

  • UTF-8并不遵循哈夫曼编码(Huffman Coding)

当然这是废话,他俩本来就是不同的编码,但是UTF-8并没有理想中那么“紧凑(compact)”,存在一些无用信息。比如一个4字节的utf8编码后的字符表示为:

11110xxx 10xxxxxx 10xxxxxx 10xxxxxx

这样设计很明显:utf8是一种无前缀编码,解码时不会混淆。最开始的11110暗示了该字符有4个字节(4个1),后面每个字节前的10代表这个字节是该字符剩下的字节,xxx就代表有效信息。现在网友的问题就是,utf8所有剩余字节的前缀10都是多余的!

这个质疑很自信,首字节的前缀已经暗示了总字节数,不再需要后续字节了。从信息论的角度,一个“意思”用不同的方式暗示2遍是在浪费信息。所以上面这个字符可以写成:

11110000 xxxxxxxx xxxxxxxx xxxxxxxx

这样子1个字符就节省了3*2=6个bit,如果这样设计utf8的话,互联网效率将大大提升。

提不提升先放一边,因为很快有stack大神回复了:

图中2个大神分别陈述了utf8采用这种“多前缀”的编码方案的2点理由,我来简单翻译一下:

  • 理由1:“多前缀”有利于网络传输时同步

Joachim Sauer的意思是utf-8这样设计可以避免网络传输过程中掉帧,或者其他情况下数据发生缺失。这个想法是基于一个重要事实,即扫描utf8每一个字节的时候可以不依赖于其他字节来判断它的类型。这就是:

  • UTF-8和Huffman的本质区别

Huffman编码后的数据必须从左向右扫描才能识别每一个字符,因为每一个字符的前缀暗示了该字符的长度,所以依次排列的每一个字符都要依赖前一个邻居字符来标明自己的位置,以此递归。

而UTF-8可以从右向左扫描,甚至从中间开始!这是因为utf8每个字节都有自己的前缀,无需依赖其他的字节。这样的话,网络传输一个字符串的时候如果发生掉帧,接收方也可以通过前缀来自动同步,不用将整个字符串重传一遍。但我想说的是:

  • 网络传输不需要UTF-8

可能有人要反驳我,先别急,我来给你反正:如果说UTF-8有用的话,那就是说我们一直在利用utf8的前缀来保障网络传输的同步,从而提高了效率,但事实上,几乎所有的网络数据在解析出其中的字符串之前都至少经过网络层或者应用层的数据完整性校验,比如http的校验,在校验阶段就能保证所传输的所有数据的完整性,在此之后解析出的字符串自然是完整的,这样UTF-8前缀提供的优点现在变得一无是处。

既然utf8的前缀机制在网络传输中根本没用到,那这种前缀显然就是资源浪费了,正如图一中knowledge所质疑的。解决方案也显而易见,就是换一种编码方案,比如Huffman编码。

UTF-8只是不适用于网络传输,但它本身是一个优良的设计,正如图二中Remy Lebeau提出的理由二一样。

  • 理由2:UTF-8提供了更好的数据索引

把字符串想象成一个数据库。

都知道索引是一种避免数据库全盘扫描的好办法,那么Huffman编码只提供了1种索引:通过每个字符的前缀来跳跃式地检索数据。而UTF-8显然不止一种索引,除了像Huffman那样索引,还可以逆向索引,甚至可以从中间开始搜索。

综上所述,编码的本质是为数据的存储和传输服务。存储的时候使用UTF-8这种“多索引”式的编码方式,牺牲一点存储空间来换取检索的效率非常OK,但传输的时候最好使用Huffman这种“单索引”式的编码来提高传输效率。然而如今的HTTP仍然在滥用UTF-8,不知道未来能否改变?

日记


上个月经历了最幸运的一天:早上打开自己的电脑,打开浏览器后2分钟屏幕开始撕裂,10秒后黑屏,到维修店花了300对MacBook Pro拆机清理后正常使用。

幸运之处有三,其一是本来预感要更换¥4000左右的腐蚀主板,最后省去了这笔钱;其二是之后开始使用公司16G的Win10台式机敲代码,体验非常好;其三是黑屏正好在早上,没丢失任何未同步到云端的数据。

本文分享自微信公众号 - WebHub(myWebHub),作者:金恒昱

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2019-08-02

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 使用 shadow DOM [MDN教程]

    Web components的一个重要特性是封装——可以将html标签结构、css样式和行为隐藏起来,并从页面上的其他代码中分离开来,这样不同的功能不会混在一起...

    Jean
  • 信息论III:寻找序列化的极限

    来自【奇怪的知识】系列的第三篇,承接上文《最优二叉树与Huffman编码》的第1~第5章,本文从第6章开始。

    Jean
  • 字节序: 一个不是很重要的概念

    我们将一个4字节的汉字存入一段4字节的物理容器里, 该怎么存放? 直觉都是从左往右依次写入, 但也可以从右向左写, 甚至可以先写入奇字节再写偶字节, 这样比划下...

    Jean
  • 字节流与字符流,字节流和字符流的使用哪个多?

    而上一篇的java 读写操作大文件 BufferedReader和RandomAccessFile

    ydymz
  • JavaScript 有个 Unicode 的天坑

    最近笔者在项目中遇到了emoji表情的处理,期间发现js处理多字节字符时会有较多坑,记录一下与各位分享。

    疯狂的技术宅
  • 第三十四章:SpringBoot配置类WebMvcConfigurerAdapter

    恒宇少年
  • Unicode与JavaScript详解

    上个月,我做了一次分享,详细介绍了Unicode字符集,以及JavaScript语言对它的支持。下面就是这次分享的讲稿。 ![](/blogimg/asset/...

    ruanyf
  • Unicode与JavaScript详解

    上个月,我做了一次分享,详细介绍了Unicode字符集,以及JavaScript语言对它的支持。下面就是这次分享的讲稿。 ? 一、Unicode是什么? Uni...

    ruanyf
  • 关于毕设的一些事

    仇诺伊
  • AI相机,请把我拍成“Angelababy ”!

    前不久,雷军发布了一条爱心加美图的微博,拉开了小米和美图战略合作的大幕。同时,小米正式宣布两家品牌达成战略合作关系,美图公司将美图手机的品牌、影像技术和二级域名...

    镁客网

扫码关注云+社区

领取腾讯云代金券