深入理解字符编码

一、前言

字符编码这个问题,困扰了无数程序员,一不小心就会掉进坑里,每当在开发中遇到乱码或者emoji表情符的奇怪问题时总是让人头疼不已,本文就来从根源上研究一下字符编码的本质和原理。

二、何为编码

编码的本质其实就是翻译,举个几个🌰:

  1. 两个说普通话的中国人进行交流时,是不需要编码的,一个人说「你好」,另一个就能直接听明白意思,反之亦然。
  2. 一个中国人和美国人交流时,就需要多一个中文到英文、和英文到中文的翻译过程,才能实现双向交流。
  3. 一个人类和计算机交流时,也是一样的道理,大家都知道计算机只认识二进制0和1,因此必须把人类语言转为二进制,才能把信息传递给计算机,这个过程叫做编码(encoding),反之则称为解码(decoding)。

三、怎么编码

1. ASCII

一种直观的想法就是,制作一个映射表,把人类语言和计算机二进制对应起来就行了,这样的思想就孕育出了ASCII编码(因为是美国人设计的,所以只有常用英文字符),如下表所示,非常直观:


USASCII_code_chart

2. Unicode

但是ASCII表太小了,最多只能编码128个字符,但人类语言又那么多,显然无法满足需求,于是世界各地的人们就分别设计了符合自己语言需求的映射表。在自己的地区使用时是没有问题的,但是一旦进行国际交流,由于映射规则各不相同,就会导致混乱。

于是人们设计了一个很大的映射表——Unicode,总共可以编码100多万个字符(最多到 0x10FFFF),目的是为了容纳世界上所有的人类语言。Unicode为每个字符分配了一个固定的数值,称为编码点(Code Point),这个值是全局唯一的。而且Unicode向前兼容 ASCII,原先在 ASCII 中定义的字符映射,在 Unicode 中也是一模一样的。

3. UTF-8

按理说设计好了 Unicode,大家都按照 Code Point 编码解码,混乱的问题就已经解决了,但是还有一个因素要考虑,就是存储成本。

Unicode设计是三个字节,如果不加考虑直接存储 Code Point,那么所有的字符都需要占用三个字节。比如 'A',如果使用ASCII,则一个字节即可 0x41,如果使用 Unicode,则要编码为 0x000041,这凭空多出来两个字节,对于英语文本来说完全是一个额外的存储开销。

为了降低存储成本,人们发明了变长编码,这里要注意下,并不是重新定义映射规则,还是用的 Unicode 的定义,只是以一种更加灵活的形式来存储以节约空间。以目前通用性最高的 UTF-8 为例,原本只需要一个字节的 ASCII 字符,仍然只占一个字节,而像中文及日语这样的复杂字符就需要2个到3个字节来存储。

UTF-8 的规则挺简单的:

  • 对于单字节的符号,字节的第一位设为0,后面7位为这个符号的 Unicode 码。因此对于英语字母,UTF-8 编码和 ASCII 码是相同的。
  • 对于n字节的符号(1 < n <= 4),第一个字节的前n位都设为1,第n + 1位设为0,后面字节的前两位一律设为10。剩下的没有提及的二进制位,全部为这个符号的 Unicode 码。

维基百科的一览表:

Number of bytes Bits for code point First code point Last code point Byte 1 Byte 2 Byte 3 Byte 4
1 7 U+0000 U+007F 0xxxxxxx
2 11 U+0080 U+07FF 110xxxxx 10xxxxxx
3 16 U+0800 U+FFFF 1110xxxx 10xxxxxx 10xxxxxx
4 21 U+10000 U+10FFFF 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx

四、Emoji

😝😊😂……这些表情符大家应该都已经不陌生了,但它们并不是什么新的概念,其实也是 Unicode 的一部分,比如这个表情 😀的Code Point是:0x1F600,查上面的 UTF-8 编码表可以看出需要4个字节来编码:0xF09F9880。完整 emoji 列表可以参见这里:https://unicode.org/emoji/charts/full-emoji-list.html

MySQL emoji问题:
UTF-8 是能支持所有的 Unicode 字符的,因此按理说 emoji 不应该会导致问题,但是在MySQL里实现的 utf8 最长只使用3个字节,如果向一个编码为 utf8 的列中插入一个表情符时,就会报类似Incorrect string value: '\xF0\x9F\xA6\x96 ...' for column 'name'
这样的错,可以看出此时想要插入的值已经有四个字节了,因此需要指定该列编码格式为 utf8mb4 才行。

五、参考资料

http://cenalulu.github.io/linux/character-encoding/
http://www.ruanyifeng.com/blog/2007/10/ascii_unicode_and_utf-8.html
https://en.wikipedia.org/wiki/ASCII
https://en.wikipedia.org/wiki/Unicode
https://en.wikipedia.org/wiki/UTF-8

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

推荐阅读更多精彩内容

  • 大概每个人在使用软件时都遇到过乱码的问题,这是由于字符的编码和解码方式不一致导致,我们知道计算机只认识二进制数据,...
    楚客阅读 1,415评论 1 9
  • 字符是用户可以读写的最小单位。计算机所能支持的字符组成的集合,就叫做字符集。字符集通常以二维表的形式存在。二维表的...
    刘惜有阅读 8,065评论 2 14
  • 最近在开发中遇到了点Emoji相关的问题,便去了解了一下Emoji的编码规则,发现其中涉及了许多字符集与字符集编码...
    黎清海阅读 10,257评论 3 15
  • 1. ASCII   我们知道,计算机内部是通过二进制数据进行操作的,所有的信息最终都会转换为一个二进制值,二进制...
    骑着乌龟去看海阅读 1,633评论 0 4
  • 想必大家都读过西游记,应该都对孙悟空这个人物并不陌生,他是吴承恩笔下塑造的最成功的人,敢爱敢恨,性格鲜明,天真烂漫...
    东阁堂主阅读 446评论 0 0