美文网首页
深入理解字符编码

深入理解字符编码

作者: 木易光_ | 来源:发表于2019-06-12 16:32 被阅读0次

一、前言

字符编码这个问题,困扰了无数程序员,一不小心就会掉进坑里,每当在开发中遇到乱码或者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

相关文章

  • 深入理解Emoji(三) —— Emoji详解

    深入理解Emoji(一) —— 字符集,字符集编码深入理解Emoji(二) —— 字节序和BOM Emoji字符是...

  • 深入理解字符编码

    大概每个人在使用软件时都遇到过乱码的问题,这是由于字符的编码和解码方式不一致导致,我们知道计算机只认识二进制数据,...

  • 深入理解Python字符编码

    不论你是有着多年经验的 Python 老司机还是刚入门 Python 不久,你一定遇到过UnicodeEncode...

  • 深入理解字符编码

    一、前言 字符编码这个问题,困扰了无数程序员,一不小心就会掉进坑里,每当在开发中遇到乱码或者emoji表情符的奇怪...

  • 2018-11-08

    今天,我们深入学习了字符串。学习了字符串编码: python中的字符采用的是Unicode编码 a.什么是编码 ...

  • 编码

    参考:字符编码常识及问题解析深入分析 Java 中的中文编码问题 关于字符编码,你所需要知道的 编码是什么? 编码...

  • 编码浅谈

    为什么要熟悉编码的本质?深入理解计算机软硬件知识深入理解计算机背后的语言 一、先来理解编码 广义的理解:编码就是交...

  • [转]【字符编码】彻底理解字符编码

    一、前言 在解决昨天的问题时,又引出了很多新的问题,如为什么要进行编码,这些编码的关系如何,如ASCII,IOS-...

  • 理解字符编码

    什么是字符编码 我们知道编程就是我们人类给计算机发送指令让计算机进行计算,先抛开我们怎样给计算机发指令这个问题不说...

  • 深入理解Emoji(一) —— 字符集,字符集编码

    最近在开发中遇到了点Emoji相关的问题,便去了解了一下Emoji的编码规则,发现其中涉及了许多字符集与字符集编码...

网友评论

      本文标题:深入理解字符编码

      本文链接:https://www.haomeiwen.com/subject/kvqynqtx.html