平时我们经常会遇到各种各样的字符编码,最常见的就是 ASCII
、UTF-8
除此之外还有 GB2312
、GBK
、EASCII
等等很多的字符编码。我们经常提到的Unicode
是一个字符集,并不是一种字符编码方案。但是这些编码方案到底是如何将字符编码的,对应的历史发展关系又是怎样的呢?
字符集术语
在讲述字符编码之前,这里统一一下字符集术语。这部分是纯概念的部分,不感兴趣的同学可以直接跳过这部分。
-
字符
字符是指字母、数字、标点、表意文字(比如汉语)、符号,或其他文本形式的书写"原子"。由统一字符集(Universal Character Set, UCS)
首创,为多种语言中的很多字符开发了一系列标准化的文本名称,它们常用来便捷的命名字符,而且不会与其他字符冲突。 -
字形
描述字符的笔画图案或唯一的图形化形状。 -
编码后的字符
分配给字符的唯一数字编号,这样我们就可以操作它了。 -
编码空间
计划用于字符编码的整数范围。 -
编码宽度
每个(固定大小的)字符编码所用的位数。 -
字符集
特定的工作字符集(全体字符的一个子集)。 -
编码后的字符集
组成字符库(从全球的字符中选出若干字符)的已编码字符集,并为每个字符分配编码空间的一个代码。换句话说,它把数字化的字符代码映射为实际的字符。 -
字符编码方案
把数字化的字符代码编码成一系列二进制码(并能相应地反向解码)的算法。
各种编码方案的历史及编码方式
计算机首先是在美国发明出来的,为了使美国常用的一些字符能在计算机中进行操作,他们就对美国现有的字符进行编码。首先出现的比较规范的编码方案就是ASCII码
。
ASCII码
ASCII码 (American Standard Code for Information Interchange,美国信息交换标准代码)
这种编码方案采用一个字节表示一个字符,一个字节 8
个 bit
位 2^8
可以表示 256
个状态,但是其中只使用了 128
个状态,最高位始终为 0
。其中 0 ~ 31
表示控制字符,32 ~ 126
表示可显示的字符,127
表示删除。ASCII码对照表。在美国这个字符编码方案是够用的,但是随着计算机的发展,传到了其他国家,其他国家的一些字符并没有在这套编码方案内,当然也就无法显示和控制了。人们就想起了剩下的那 128
个没有使用的状态对目前的 ASCII码
进行扩展,这就是EASCII(Extended ASCII,延伸美国标准信息交换码)
。
EASCII码
EASCII码
有很多种,比较常见的有 CP437
,ISO/IEC 8859系列
。他共同特点就是前 128
位的状态和 ASCII码
是一样的。而后面的则根据不同的国家对应编不同的字符,这样就解决了很多国家的字符编码问题。但是到了亚洲大多采用表意文字,比如汉字多达几千上万的字符,这样这套编码方案就又不能适应了。所以就又出现了其他的编码方案,例如中文编码方案 GB2312
、GBK
等等各种不同的编码方案。下面以GB2312
为例讲解这类编码方案。
GB2312
由于汉字众多,单字节的状态位已经不够用,所以中国人老实不客气的在加一个字节这样 2
个字节 16
位,最多就可表示 2^16 = 65536
个状态。GB2312
是基于区位码设计的,区位码把编码表分为 94
个区,每个区对应
94
位,每个字符的区号和位号组合起来就是该汉字的区位码。区位码一般用十进制数来表示,如 1601
就表示 16
区 1
位,对应的字符是"啊"。在区位码的区号和位号上分别加上 0xA0
就得到了 GB2312
的编码,比如字符"啊"的编码就是 0xB0A1
。GB2312简体中文编码表。其中有很多的状态位是没有使用的,
GB2312
的编码范围是 0xA1A1~0xFEFE
,就算是这个编码范围内的也有很多是没有使用的。后来的 GBK
、GB18030
等都是在此基础上,又增添了其他的一些字符,这里不做具体叙述。
Unicode
随着越来越多的编码方案出现,相互之间的交流变得复杂起来。这时 Unicode
出现了,Unicode字符表它把世界上所有的字符都对应起来一个编码。但 Unicode
仅仅只是一个字符集,它只规定了符号的二进制代码,却没有规定这个二进制代码应该如何编码存储。后续对此字符集进行编码,提出了不同的编码方案,其中有 UTF-8
,UTF-16
, UTF-32
。下面以 UTF-8
为例讲解。
UTF-8
UTF-8(Unicode Transformation Format - 8)
,UTF-8
使用的是变宽编码,不像上面提到的,说是一个字节或两个字节的长度,则所有的字符都是那么长。
UTF-8
占用最小占用 1
个字节,最大占用 6
个字节。编码方式为:
字符代码的二进制位 | 字节1 | 字节2 | 字节3 | 字节4 | 字节5 | 字节6 |
---|---|---|---|---|---|---|
0~7 | 0xxxxxxx | |||||
8~11 | 110xxxxx | 10xxxxxx | ||||
12~16 | 1110xxxx | 10xxxxxx | 10xxxxxx | |||
17~21 | 11110xxx | 10xxxxxx | 10xxxxxx | 10xxxxxx | ||
22~26 | 111110xx | 10xxxxxx | 10xxxxxx | 10xxxxxx | 10xxxxxx | |
27~31 | 1111110x | 10xxxxxx | 10xxxxxx | 10xxxxxx | 10xxxxxx | 10xxxxxx |
举例来说明一下,Unicode
中字符代码 90(字符为" Z ")
的二进制码为1011010
7位
,这对应的编码就是一个字节长度,01011010。Unicode
中字符代码 5073(字符" Ꮡ ")
的二进制码为 1001111010001
13位
的则需要用三个字节。编码后为11100001 10001111 10010001。
总结
像 ASCII码
这些,既是字符集,又是编码方案,而 Unicode
仅仅是一个字符集,并不是一个编码方案。我们最常用的编码方案就是 ASCII码
和 UTF-8
。而大多数的编码方案都是兼容 ASCII码
的。这里只是在众多的编码方案中,挑出几种来介绍,如果对其他的一些编码方案感兴趣,可以自己再去查阅有关资料。这是一系列文章的其中一篇,你可以在这儿Encode & Decode集序找到他其他的兄弟。
参考
- 陈娟,赵振平[译]. HTTP权威指南:人名邮电出版社
- 常用字符集编码详解:ASCII 、GB2312、GBK、GB1803...