# 字符集的那些知识(相信你能看懂)

字符集的那些知识(相信你能看懂)

文章目录

  • 字符集的那些知识(相信你能看懂)
    • 1 字符集组织与标准
    • 2 字符集与对应的编码方式等
      • 2.1 字符集Unicode 1.0(UCS-2)
      • 2.2 字符集Unicode 2.0(UCS-4)
    • 3 Unicode(UCS)码点值
    • 4 编码方式说明
      • 4.1 用UTF-16(UCS-2)、UTF-32(UCS-4)方式编码
      • 4.2 用UTF-8方式编码
    • 5 C.UTF-8与en_US.UTF-8的区别
    • 6 最后

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 个字节表示一个字符,根据字符的不同变换长度。编码规则如下:

  1. 对于单个字节的字符,第一位设为 0,后面的 7 位对应这个字符的 Unicode 码点。因此,对于英文中的 0 - 127 号字符,与 ASCII 码完全相同。这意味着 ASCII 码那个年代的文档用 UTF-8 编码打开完全没有问题。

  2. 对于需要使用 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 最后

爱你

你可能感兴趣的:(IT,开发语言)