View on GitHub

nodes

个人笔记

字符编码基础知识

开发过程中经常遇到各种编码问题,只要把编码调整一致就可以解决问题。然而并没有对编码有一个很清楚的了解,于是查了一些资料,用自己的话总结了一下,梳理了一下概念和关系。有不对的地方欢迎大家提出拍砖,轻拍谢谢。

What & Why

计算机存储单元bit只能有两种状态,只能存储 0 和 1,通过 0 和 1 的组合代表不同的信息; 这些 0 和 1 的组合人是不能够直接理解的,所以要把这些这些 0,1 进行转换,转换成文字、声音、图像等等,反之一样要把文字图片等转换成 0 和 1 进行存储和传输;

在信息的存储和网络传输的过程中我们要把信息转换成 0 和 1 的序列,这个转换过程就是编码(Encoding) 从硬盘和网络中读取的到的 01 序列要进行逆转换才能得到我们能够理解的信息,这个逆转换过程就是解码(Decoding)

基本概念

字符编码的发展的几个阶段

第一阶段:ASCII 及 ASCII 扩展

美国人发明了计算机,也创造了第一套字符编码ASCII(American Standard Code for Information Interchange 美国信息交换标准码)。 每 8 个晶体管为一组,组成一个 Byte,可以产生 256 种组合;美国人使用其中的 128 种组合指定了 ASCII,占用了 0-127 段; 占用一个 Byte 中的后七位,第一位为 0,例如 A 是 65(01000001)、B 是 66(01000010);包括终端状态、标点符号、数字、英文大小写字母; ASCII编码图

但是 ASCII 只能表示显示 26 个基本拉丁字母、阿拉伯数字和英式标点符号;然后欧洲人不乐意了,字母符号不够用啊。 欧洲人决定在 ASCII 上扩充了表格符号、计算符号、希腊字母和特殊的拉丁符号;0-127 段和 ASCII 完全相同,占用了 128-255 这段存储空间。称为EASCII(Extended ASCII 延伸美国标准信息交换码) EASCII编码图

在这个阶段每个字符在计算机存储和传输中使用一个字节进行编码。

第二阶段:百花齐放

很快中国、日本、韩国等等很多国家都要使用计算机,所以 EASCII 也根本够用,所以就各自制定了一些列字符集,以下几个为应用较多的几个中文字符集:

一个字节(Byte)最多可以有 256(2 的 8 次方)中组合方式,应对亚洲图形文字明显不够用,所以采用两个字节长度进行编码。 以上只是中国折腾出来的东西,其它国家应该一样很热闹多产。

第三阶段:万宗归一-通用字符集

很快这种百发齐放的繁荣就暴露了出了问题,各个国家都在定制自己的字符编码,乱成一锅粥了,同一个二进制在不同的编码方案下表示的是不同的字符;
这时一些国际组织站出来做编码统一这件事,最后制定了Unicode(国际码), Unicode 从 0 开始为每个符号指定了一个编号,叫做“码点”; 通常在表示一个 Unicode 值的 16 进制数前面加上U+,例如码点 0 的符号就是 nullU+0000 = null; Unicode 的码点取值范围为U+000000-U+10FFFFF共 1114112 个可用码点,但是并未全部使用; Unicode 平面 Unicode 并不是采用从小到大、从前到后这种方式对字符进行编码的,而是将 1114112 个可用码点划分成了 17 个平面

可用看出 Unicode 使用第一个字节作为平面编码,其余两个字节进行字符编码,每个平面可用编码 65536(2^16)个字符。 其中第平面 0 比较特殊,包含了大多数最常用的语言字符和符号,称为基本平面(BMP) 其它 16 个平面称为辅助平面,具体平面分布可用参考Unicode 字符平面映射

第四阶段:完善

Unicode 是一个通用字符集,对世界上大部分文字系统进行了整理、编码,解决了编码字符集不统一的问题。 但是 Unicode 只制定了字符码点,没有定制字符编码方案, 比如汉字“中”的码点十六进制数是4E2D,转换为二进制是100111000101101共 15 位,至少需要 2 个 Byte,但是也可以使用 3 个或 4 个 Byte; 那么问题来了:

  1. 划分问题:计算机无法确定使用几个字节解码成一个字符;
  2. 流量问题:如果统一使用四个字节编码一个字符,那么对于英文字母和数字这种使用一个字节就可以编码的字符是极大的浪费;

为了解决这个问题很多厂商都有自己的 Unicode 编码方案,最后形成了多种 Unicode 编码实现方案,UTF-8 是互联网使用最广的一种方式;

UTF-8 编码方案

UTF-8 是 Unicode 的实现方式之一,UTF-8 是一种变长的编码方式

例子:以“中”字为例

Unicode 编码 4E2D(0100 1110 0010 1101)
需要 3 个字节来存储,即为 1110 xxxx 10xx xxxx 10xx xxxx
填充后 1110 0100 1011 1000 1010 1101
转换为十六进制 E4B8AD

“中”的 Unicode 编码为4E2D,UTF-8 编码为E4B8AD,二者的编码并不相同,是通过程序转换的

字符集、编码字符集和字符编码

字符集是一系列特定用途字符的集合,编码字符集中的每个字符都被绑定了一个唯一数值,字符编码是编码字符和计算机字节的映射,如下图: 字符,码点,字符编码关系 字符编码主要用于解决存储和传输的问题,而编码字符集就是给字符集里面每个字符提供一个序号。

同一个字符集可能有多种编码字符集,同一编码字符集还可能有多种不同的字符编码 同一编码字符集的不同字符编码 有些编码字符集合字符编码是一体的例如:GBK ASCII。 有些编码字符集没有规定字符编码方案例如 Unicode 只是一个编码字符集。 Unicode 的字符编码又有多种字符编码实现方案例如:UTF-8、UTF-16 等。

参考

Character encodings for beginners Character encodings: Essential concepts Unicode - 维基百科 字符编码笔记:ASCII,Unicode 和 UTF-8 字符编码的前世今生