字符集知识体系

113 阅读5分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第4天,点击查看活动详情

字符集知识体系

背景

字符集这个东西说难不难,但说简单又很难有人能够讲清楚,因此这里对字符集知识进行一个总结。

两个概念

字符集

字符集是很多个字符的集合,例如 GB2312 是简体中文的字符集,它收录了六千多个常用的简体汉字及一些符号,数字,拼音等字符。

字符编码

字符编码是字符集的一种实现方式,把字符集中的字符映射为特定的字节或字节序列,它是一种规则,应该说是一种存储规则,即使用多个字节存储该字符。

也可以说字符编码是一种 (规则)算法,是一种可以把字符集中的字符按照某种规则转化为电脑可识别的机器码的算法,同时也是可以把机器码按照某种规则转化为指定字符集中的字符的算法。

历史溯源

首先来张图看一下字符集的关系,该图来自roadmap.sh上字符集介绍,如下分别提到了UTF-8、UTF-16、ASCII(美国信息交换标准代码)、Unicode等多个名词。

Aspose.Words.a42d677d-4c00-49ec-aede-9802d8edb44e.001.png

首先是字符编码的一个起源,世界上第一台计算机,1945年由美国宾夕法尼亚大学的两位教授-莫奇利和埃克特设计和研制出来,美国人起草了计算机的第一份字符集和编码标准,叫 ASCII(American Standard Code for Information Interchange,美国信息交换标准代码),详细ASCII编码标识见ASCII:字符集与字符编码的起源-IT Blog;ASCII由7位二进制位标识128个字符(0000000~01111111),一个字节足够用。

随着计算机的发展,在不同的地区和国家又出现了很多字符编码,比如: 大陆的 GBK、港台的 BIG5, 日本的 Shift JIS等等。但由于字符编码不同,经常会出现乱码的问题,比如:对于同一个二进制数据,不同的编码会解析出不同的字符。因此急需一种统一的规则来解决这个问题,因此出现了Unicode字符集。

Unicode

Unicode 简介

Unicode 是国际标准字符集,它将世界各种语言的每个字符定义一个唯一的编码,以满足跨语言、跨平台的文本信息转换。Unicode 字符集的编码范围是 0x000000 - 0x10FFFF , 可以容纳一百多万个字符, 每个字符都有一个独一无二的编码,也即每个字符都有一个二进制数值和它对应,这里的二进制数值也叫码点 , 比如:汉字 "中" 的 码点是 0x4E2D, 大写字母 A 的码点是 0x41, 具体字符对应的 Unicode 编码可以查询 Unicode字符编码表。

Unicode 字符存储

Unicode 是一个符号集, 它只规定了每个符号的二进制值,但是它并没有规定符号具体如何存储。Unicode 字符集的编码范围是 0x0000 - 0x10FFFF,因此需要 1 到 3 个字节来表示。

那么,对于三个字节的 Unicode字符,计算机怎么知道它表示的是一个字符而不是三个字符呢 ?

如果所有字符都用三个字节表示,那么对于那些一个字节就能表示的字符来说,有两个字节是无意义的,对于存储来说,这是极大的浪费,假如 , 一个普通的文本 , 大部分字符都只需一个字节就能表示,现在如果需要三个字节才能表示,文本的大小会大出三倍左右。

因此,Unicode 出现了多种存储方式,常见的有 UTF-8、UTF-16、UTF-32,它们分别用不同的二进制格式来表示 Unicode 字符;UTF-8、UTF-16、UTF-32 中的 "UTF" 是 "Unicode Transformation Format" 的缩写,意思是"Unicode 转换格式",后面的数字表明至少使用多少个比特位来存储字符,比如:UTF-8 最少需要8个比特位也就是一个字节来存储,对应的, UTF-16 和 UTF-32 分别需要最少 2 个字节 和 4 个字节来存储。

详细的 UTF-8 UTF-16 UTF-32 如何存储,参考:www.51cto.com/article/661…

UTF-8 UTF-16 UTF-32

UTF-8、UTF-16、UTF-32只是编码规则,Unicode才是字符集。

总结

Aspose.Words.a42d677d-4c00-49ec-aede-9802d8edb44e.001.png

再看开始时候的图片,一段文字通过字符集确定该字符对应的二进制位标识,然后通过字符编码选择不同的方式存储该二进制位,然后计算机再根据相同的字符编码方式进行解码获得相应的信息。

其中ASCII既是字符集,又是字符编码;而Unicode是字符集,UTF-8、UTF-16、UTF-32是字符编码。

参考

ASCII和Unicode参考:roadmap.sh/guides/char…

UTF-8和UTF-16参考:Unicode、UTF-8、UTF-16 终于懂了-51CTO.COM

ASCII起源参考:ASCII:字符集与字符编码的起源-IT Blog