字符集的那些知识(相信你能看懂)
文章目录
1 字符集组织与标准
ASCII字符集(American Standard Code for Information Interchange,美国信息交换标准码),它使用7 bits来表示一个字符,总共表示128个字符。(IBM后来扩展到8bits,256个字符)
英文字母加特殊字符不会超过256个,一个字节就够了,但其他一些文字就不行,像汉字就上万个,于是又出现了其他各种字符集,这样不同的字符集交换数据时就有问题了,可能你用某个数字表示字符A,但在另外的字符集这个数字表示的却不是A,这样交互起来就麻烦了,于是就出现了Unicode和ISO这样的组织来统一制定一个标准,任何一个确定的数字只对应一个字符,ISO取的名字叫UCS(Universal Character Set),Unicode取的名字就叫unicode了。
组织名 | 字符集标准 | 字符集 | 备注 |
---|---|---|---|
美国国家 | ASCII标准 | ASCII(7比特位) | 英文字符,被Unicode/UCS兼容 |
Unicode | Unicode标准 | Unicode 1.0(2字节)、Unicode 2.0(4字节) | 所有语言通用 |
ISO | UCS (Universal Character Set)标准 | UCS-2(2字节)、UCS-4(4字节) | 所有语言通用 |
中国 | 汉字专用 | GB2312、GBk、GB18030(GB18030-2000、GB18030-2005) | 终将淘汰,本文不深入探讨 |
其他 | 其他专用字符集 | 终将淘汰,本文不深入探讨 |
Unicode与ISO的字符集标准的编码是完全一样的,我们一般称Unicode编码更为普遍。
2 字符集与对应的编码方式等
2.1 字符集Unicode 1.0(UCS-2)
用两个字节(16bit)来表示所有字符,即最多可以表示2的16次方个字符(65536个)
Unicode版本1下有两种字符集编码方式:UTF-8 和 UTF-16,这里说的是字符集编码方式,不是字符集
在文件的开头用这几个字节标识文件的编码方式:
Unicode字符集(ISO字符集) | Unicode编码方式(ISO编码方式) | 文件开头字节 | 存储占用字节数 |
---|---|---|---|
Unicode 1.0(UCS-2) | UTF-8(无) | EF BB BF | 1-4 |
Unicode 1.0(UCS-2) | UTF-16(UCS-2) | FE FF | 2 |
注:UCS就是前面说的ISO制定的标准,和Unicode是完全一样的,只不过名字不一样,UCS-2对应UTF-16,UTF-8是没有对应的UCS
2.2 字符集Unicode 2.0(UCS-4)
起初,Unicode使用两个字节(16位)来编码字符,后来,当发现不够时(全世界语言字符那么多),1996年它被扩展到四个字节(32位),对应于UCS-4、Unicode 2.0版本,用四个字节表示所有字符。
在文件的开头用这几个字节标识文件的编码方式:
Unicode字符集(ISO字符集) | Unicode编码方式(ISO编码方式) | 文件开头字节 | 存储占用字节数 | Unicode 2.0新增的 |
---|---|---|---|---|
Unicode 2.0(UCS-4) | UTF-8(无) | EF BB BF | 1-7 (理论上) | |
Unicode 2.0(UCS-4) | UTF-16(UCS-2, little endian) | FE FF | 2 | |
Unicode 2.0(UCS-4) | UTF-16(UCS-2, big endian) | FF FE | 2 | 是 |
Unicode 2.0(UCS-4) | UTF-32(UCS-4, little endian) | FF FE 00 00 | 4 | 是 |
Unicode 2.0(UCS-4) | UTF-32(UCS-4, big-endian) | 00 00 FE FF | 4 | 是 |
注:
UCS就是前面说的ISO制定的标准,和Unicode是完全一样的,只不过名字不一样,UCS-2对应UTF-16,UCS-4对应UTF-32,UTF-8是没有对应的UCS。
Big endian与Little endian的区别:Unicode码可以采用UCS-2格式直接存储,以汉字"严"为例,Unicode码是4E25,需要用两个字节存储,一个字节是4E,另一个字节是25。存储的时候,4E在前,25在后,就是Big endian方式,我们一般称之为"大头方式";25在前,4E在后,就是Little endian方式,我们一般称之为"小头方式"。大头方式对人类阅读友好,在Unicode 1.0时,只有小头方式。
3 Unicode(UCS)码点值
码点是Unicode标准中很重要的一个概念,一个码点对应一个字符。
- 【汉】的Unicode码点值是【0x6C49】
kevin@TM1701-b38cbc23:~$ echo -e '\u6c49'
汉
- 需要注意的是,一个单一的抽象字符可能对应一个以上的码位。例如,
Ω
既可以表示大写的希腊字母Omega,码位是U+03A9
,也可以表示物理学中的欧姆符号,码位是U+2126
。
kevin@TM1701-b38cbc23:~$ echo -e '\u03a9'
Ω
kevin@TM1701-b38cbc23:~$ echo -e '\u2126'
Ω
- 单个抽象字符也可以由一系列码位的序列来表示。例如,
é
的码位是U+00E9
,它也可以由小写字母e
(码位为U+0065
)'
(Combining Acute Accent)(码位为U+0301
)组合而成。
kevin@TM1701-b38cbc23:~$ echo -e '\u00e9'
é
kevin@TM1701-b38cbc23:~$ echo -e '\u0065\u0301'
é
在Unicode标准中,码点的表示方法通常是使用它们的十六进制,并加上U+
前缀。
4 编码方式说明
注:
Unicode 1.0、Unicode 2.0:是字符集
UCS-2、UCS-4:既是字符集也是编码方式
UTF-16、UTF-32:是编码方式,等同 UCS-2 与 UCS-4 编码方式,因为是固定字节长度,所以在存储时无需重新编码,直接存储Unicode编码即可。
UTF-8:是编码方式,是存储Unicode字符编码的存储编码方式,非固定长度,根据Unicode字符编码的长度来确定存储该字符需要的字节长度
为什么有了UTF-16、UTF-32编码方式,还要UTF-8编码方式:因为例如在中英文或其他文字大量混合时,UTF-8编码方式可以节省大量存储空间,英文在用UTF-8编码方式存储时,只需占用1个字节,而UTF-32就需要占用4个字节
下面以【汉】举例说明,【汉】的Unicode码点值是【0x6C49】,即为【01101100 01001001】
4.1 用UTF-16(UCS-2)、UTF-32(UCS-4)方式编码
UTF-16(UCS-2)、UTF-32(UCS-4)方式无需重新编码,直接使用字符的Unicode码点值即可。
-
当用UTF-16(UCS-2)编码方式时,则【汉】直接存储为【01101100 01001001】即可,固定占用16 bit,两个字节,程序解析的时候知道是UTF-16编码,就把两个字节当成一个单元来解析,简单明了。
-
当用UTF-32(UCS-4)编码方式时,则【汉】直接存储为【00000000 00000000 01101100 01001001】,占用4个字节,前面用0占位补齐即可。
4.2 用UTF-8方式编码
UTF-8 是一个非常惊艳的编码方式,漂亮的实现了对 ASCII 码的向后兼容及减少空间占用,以保证 Unicode 可以被大众接受。
UTF-8 是目前互联网上使用最广泛的一种 Unicode 编码方式,它的最大特点就是可变长。它可以使用 1 - 7 个字节表示一个字符,根据字符的不同变换长度。编码规则如下:
-
对于单个字节的字符,第一位设为 0,后面的 7 位对应这个字符的 Unicode 码点。因此,对于英文中的 0 - 127 号字符,与 ASCII 码完全相同。这意味着 ASCII 码那个年代的文档用 UTF-8 编码打开完全没有问题。
-
对于需要使用 N 个字节来表示的字符(N > 1),第一个字节的前 N 位都设为 1,第 N + 1 位设为0,剩余的 N - 1 个字节的前两位都设位 10,剩下的二进制位则使用这个字符的 Unicode 码点值来填充。
编码规则如下(x是有效码点位):
Unicode编码长度 | Unicode 十六进制码点范围 | UTF-8 二进制 | 说明 |
---|---|---|---|
16位 | 0000 0000 - 0000 007F | 0xxxxxxx | 用于兼容ASCII |
16位 | 0000 0080 - 0000 07FF | 110xxxxx 10xxxxxx | 需要两个字节,所以第一字节前导为’110’ |
16位 | 0000 0800 - 0000 FFFF | 1110xxxx 10xxxxxx 10xxxxxx | … |
16位 | 0001 0000 - 0010 FFFF | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx | 需要两个字节,所以第一字节前导为’11110’ |
24位 | …以此类推… | ||
32位 | …以此类推… |
【汉】的Unicode码点值是【01101100 01001001】,用上面的编码规,去掉前导【0】,Unicode码点值需要占用15位,得出【汉】需要占用三个字节,所以编码后,他的最终UTF-8编码为【1110 0110 10 110001 10 001001 】
5 C.UTF-8与en_US.UTF-8的区别
C.UTF-8
: 一般来说C
,适用于计算机,C代表POSIX标准兼容的默认语言环境,只有严格的ASCII字符才是有效的,扩展后允许基本使用UTF-8;UTF-8代表字符集与编码。这一个一般用于数据库环境
en_US.UTF-8
: en_US代表美式英语;UTF-8代表字符集与编码
zh_CN.UTF-8
: zh_CN代表中国大陆汉语;UTF-8代表字符集与编码
这些会影响它们在排序顺序、大小写关系、排序顺序、数千分隔符、默认货币符号等方面有所不同。
6 最后
爱你