【编码】Unicode编码模型()

1. 为什么使用Unicode?

Unicode为每种语言中的每个字符设定了统一并且唯一的二进制编码,以满足跨语言、跨平台进行文本转换、处理的要求。

在Unicode标准中,提供了1,114,112个码点,不仅可以包含当今世界使用的所有语言文字和其他符号,也足够容纳绝大多数具有历史意义的古文字和符号。并且,Unicode给每个字符提供了一个唯一的数字,不论是什么平台,不论是什么程序,不论什么语言。 Unicode 标准已经被工业界的Leaders所采用,例如:Apple, HP, IBM, JustSystem, Microsoft, Oracle, SAP, Sun, Sybase, Unisys等等。最新的标准都需要Unicode,例如XML, Java, ECMAScript , LDAP, CORBA 3.0, WML等等,并且,Unicode是实现ISO/IEC 10646的正规方式。许多操作系统,所有最新的浏览器和许多其他产品都支持它。Unicode标准的出现和支持它工具的存在,是近来全球软件技术最重要的发展趋势。

2. Unicode与ISO 10646

历史上,有两个组织均试图“建立世界统一的字符编码”:

(1) 国际标准化组织(ISO),他们于1984年创建ISO/IEC JTC1/SC2/WG2工作组,试图制定一份“通用字符集”(Universal Character Set,简称UCS),并最终制定了ISO 10646标准。

(2) 统一码联盟,他们由Xerox、Apple等软件制造商于1988年组成,并且开发了Unicode标准(The Unicode Standard,这个前缀Uni很牛逼哦—Unique, Universal, and Uniform)。

1991年前后,两个项目的参与者都认识到,世界不需要两个不兼容的字符集。于是,它们开始合并双方的工作成果,并为创立一个单一编码表而协同工作。从Unicode 2.0开始,Unicode采用了与ISO 10646-1相同的字库和字码;ISO也承诺,ISO 10646将不会替超出U+10FFFF的UCS-4编码赋值,以使得两者保持一致。两个项目仍都独立存在,并独立地公布各自的标准。不过由于Unicode这一名字比较好记,因而它使用更为广泛。

注:通用字符集(UCS)和Unicode字符集是两个不同的主体分别发布的标准。当然,后者的英文为Unicode Character Set,缩写同样是UCS

3. Unicode编码模型

Unicode编码模型

层次

层次名称

作用

结果

第一层

抽象字符表ACR

字符范围

 

第二层

编号字符集CSS

字符编号

Unicode字符集

第三层

字符编码方式CEF

码元序列

UTF-8, UTF-16

第四层

字符编码方案CES

物理编码(确定字节序)

字节序列

第五层

传输编码语法TES

网络传输编码

base64

层次

层次名称

作用

结果

第一层

抽象字符表ACR

字符范围

第二层

编号字符集CSS

字符编号

Unicode字符集

第三层

字符编码方式CEF

码元序列

UTF-8, UTF-16

第四层

字符编码方案CES

物理编码(确定字节序)

字节序列

第五层

传输编码语法TES

网络传输编码

base64

以上5个层次被称为Unicode编码模型,其实也是Unicode编码实现的步骤。

(1)第一层:抽象字符表ACR(Abstract Character Repertoire)

ACR用于确定可以编码的字符的范围(即,确定支持哪些字符) 字符表分为是封闭的字符表和开放的字符表,封闭的字符表不允许添加新的字符,比如ASCII字符表;开放的字符表允许不断的添加新的字符,Unicode字符表就是开放字符表,另外,代码页在一定程度上也是开放的。

(2)第二层:编号(编码)字符集CSS(Coded Character Set)

为每个字符编一个唯一的编号,从而形成一个庞大的“字符编号对”的集合,这个集合就是编号字符集CSS。比如,将大写字母A编号为整数65,B编号为66等,注意:Unicode字符的编号是使用16进制数表示的。需要注意的是,编号字符集仅仅规定了每个字符的编号,并未将编号转换为二进制串。

Coded Character Set通常翻译为“编码字符集”,但由于此步骤的特征,翻译为“编号字符集”更为贴切,还可避免与之后转换为二进制时的“编码”相混淆。

Unicode用数字0-0x10FFFF来映射这些字符,最多可以容纳1114112个字符,或者说有1114112个码位。

(3)第三层:字符编码方式/格式CEF(Character Encoding Form)

在Unicode字符编码模型中,编码格式(encoding form)指定如何将每个码点表示为一个或多个编码单元序列。Unicode标准提供了三种不同的编码格式,使用8位、16位和32位编码单元,分别为UTF-8、UTF-16、UTF-32。

UTF全称:Unicode Transformation Format(Unicode转换格式),UTF-8、UTF-16、UTF-32都是将数字(码点)转换到程序数据(码元序列)的编码格式

UCS在编码上也有自己的格式:UCS-2和UCS-4等等。

(4)第四层:字符编码方案CES(Character Encoding Scheme)

将逻辑上的码元序列映射为物理上的字节序列(即,物理字符编码),字节序列仍是一个二进制串,此步骤的主要目的是确字码元序列的字节序,字节序确定之后就可以直接由计算机处理、存储了,由于UTF-8编码不存在字节序问题,所以使用UTF-8编码的字符不需要经过此层。

对于UTF-16和UTF-32,字节串行化规范必须考虑当前表示数据的系统采用的是big-endian(大端法)还是little-endian(小端法)结构。因此,Unicode标准中定义的三种编码格式,导致总共七种Unicode编码方案,分别为:UTF-8、UTF-16、UTF-16BE、UTF-16LE、UTF-32、UTF-32BE、UTF-32LE。 必须明确,字符编码格式(character encoding form)指在内存或API中的整数数据单元,与字节顺序不相关;字符编码方案(character encoding scheme)指字节串行化的数据,如I/O流或者文件,必须制定字节顺序。

(5)第五层:传输编码语法TES(Transfer encoding Syntax)

将字节序列进一步编码处理,以适合于在网络中传输。

由于历史的原因,在某些特殊的传输环境中,需要对上一层次的字符编码模式CES所提供的字节序列(字节流)作进一步的适应性编码处理。一般包括两种:

① 一种是把字节序列映射到一套更受限制的值域内,以满足传输环境的限制,例如用于Email传输的Base64编码或者quoted-printable编码(可打印字符引用编码),都是把8位的字节映射为7位长的数据。

注:Email协议设计为仅能传输7位的ASCII字符;从一个8位字节的角度来看,ASCII字符的首位始终为0,所以除去首位的0,实际有效的位数为7位,或许最初是出于节约传输流量的考虑,Email协议被设计为了仅能传输7位的ASCII字符。

② 另一种是压缩字节序列的值,如LZW或者进程长度编码等无损压缩技术。

4. UTF-32与UCS-4

在Unicode与ISO 10646合并之前,ISO 10646标准为“通用字符集”(UCS)定义了一种31位的编码形式(即UCS-4),其编码固定占用4个字节,编码空间为0x00000000~0x7FFFFFFF(可以编码20多亿个字符)。UCS-4有20多亿个编码空间,但实际使用范围并不超过0x10FFFF,并且为了兼容Unicode标准,ISO也承诺将不会为超出0x10FFFF的UCS-4编码赋值。由此UTF-32编码被提出来了,它的编码值与UCS-4相同(UTF-32/UCS-4编码单元的值也与Unicode码点的值完全相同),只不过其编码空间被限定在了0~0x10FFFF之间。因此也可以说:UTF-32是UCS-4的一个子集。

5. UTF-16与UCS-2

除了UCS-4,ISO 10646标准为“通用字符集”(UCS)定义了一种16位的编码形式(即UCS-2),其编码固定占用2个字节,它包含65536个编码空间(可以为全世界最常用的63K字符编码(例:“汉”的UCS-2编码为6C49)。为了兼容Unicode,0xD800-0xDFFF之间的码位未使用)。

但俩个字节并不足以正真地“一统江湖”(a fixed-width 2-byte encoding could not encode enough characters to be truly universal),于是UTF-16诞生了,与UCS-2一样,它使用两个字节为全世界最常用的63K字符编码,不同的是,它使用4个字节对不常用的字符进行编码。UTF-16属于变长编码。因此,UCS-2是UTF-16的一个子集。

6. UTF-8

为满足基于ASCII,面向字节的系统的需要,Unicode标准中定义了第三种编码格式UTF-8。它是一种使用8位编码单元的变宽的编码格式。

在UTF-8的编码单元种,一些高位用于指示当前字节在编码单元序列中的那一部分。8位编码单元的取值的一部分范围保留给UTF-8的编码单元序列的首字节;另一部分完全奋力的范围保留给序列中的后续字节,以保证UTF-8不重叠。

UTF -8编码格式对所有ASCII码点具有透明性。在U+0000到U+007F范围内的Unicode码点,被转换为UTF-8中单一的字节0x00到 0x7F,与ASCII码没有区别。并且,从0x00到0x7F不会出现在其他Unicode码点的UTF-8表示中的任一字节中,保证了不存在歧义。 Unicode中超出ASCII范围位于U+0080到U+07FF的其他一些非表意字母使用两个字节表示;位于U+0800到U+FFFF范围内的非代理码点使用三字节表示;超出U+FFFF的增补码点则需要四字节表示。

字节数

Unicode

UTF-8编码

1

000000-00007F(0-7)

0xxxxxxx(7)

2

000080-0007FF(8-11)

110xxxxx 10xxxxxx(11)

3

000800-00FFFF(12-16)

1110xxxx 10xxxxxx 10xxxxxx(16)

4

010000-10FFFF(17-21)

11110xxx 10xxxxxx 10xxxxxx 10xxxxxx(21)

字节数

Unicode

UTF-8编码

1

000000-00007F(0-7)

0xxxxxxx(7)

2

000080-0007FF(8-11)

110xxxxx 10xxxxxx(11)

3

000800-00FFFF(12-16)

1110xxxx 10xxxxxx 10xxxxxx(16)

4

010000-10FFFF(17-21)

11110xxx 10xxxxxx 10xxxxxx 10xxxxxx(21)

UTF-8是Internet中HTML和类似协议偏好的编码格式。 UTF-8同其他的多字节编码方式相比具有以下特点:

a) UTF-8的编码单元序列的第一个字节指明了后面所跟的字节的数目。对前向解析非常有效。多字节编码(N>1个字节):第一个字节的前N位都为1,第N+1位为0,后面N-1 个字节的前两位都为10,这N个字节中其余位全部用来存储Unicode中的码位值。

b) 从UTF-8字节流的任意位置开始可以有效的找到一个字符的起始位置。

c) UTF-8中不存在字节取值的重叠。

参考

  • unicode编码对照表(unicode编码占几个字节) – 聚集快讯 – 聚集号 (msheying.com)
  • Unicode, UTF-8, UTF-16, UTF-32, UCS-2, UCS-4是什么?_Jonny Z的博客-CSDN博客_ucs4
————————

1. 为什么使用Unicode?

Unicode为每种语言中的每个字符设定了统一并且唯一的二进制编码,以满足跨语言、跨平台进行文本转换、处理的要求。

在Unicode标准中,提供了1,114,112个码点,不仅可以包含当今世界使用的所有语言文字和其他符号,也足够容纳绝大多数具有历史意义的古文字和符号。并且,Unicode给每个字符提供了一个唯一的数字,不论是什么平台,不论是什么程序,不论什么语言。 Unicode 标准已经被工业界的Leaders所采用,例如:Apple, HP, IBM, JustSystem, Microsoft, Oracle, SAP, Sun, Sybase, Unisys等等。最新的标准都需要Unicode,例如XML, Java, ECMAScript , LDAP, CORBA 3.0, WML等等,并且,Unicode是实现ISO/IEC 10646的正规方式。许多操作系统,所有最新的浏览器和许多其他产品都支持它。Unicode标准的出现和支持它工具的存在,是近来全球软件技术最重要的发展趋势。

2. Unicode与ISO 10646

历史上,有两个组织均试图“建立世界统一的字符编码”:

(1) 国际标准化组织(ISO),他们于1984年创建ISO/IEC JTC1/SC2/WG2工作组,试图制定一份“通用字符集”(Universal Character Set,简称UCS),并最终制定了ISO 10646标准。

(2) 统一码联盟,他们由Xerox、Apple等软件制造商于1988年组成,并且开发了Unicode标准(The Unicode Standard,这个前缀Uni很牛逼哦—Unique, Universal, and Uniform)。

1991年前后,两个项目的参与者都认识到,世界不需要两个不兼容的字符集。于是,它们开始合并双方的工作成果,并为创立一个单一编码表而协同工作。从Unicode 2.0开始,Unicode采用了与ISO 10646-1相同的字库和字码;ISO也承诺,ISO 10646将不会替超出U+10FFFF的UCS-4编码赋值,以使得两者保持一致。两个项目仍都独立存在,并独立地公布各自的标准。不过由于Unicode这一名字比较好记,因而它使用更为广泛。

注:通用字符集(UCS)和Unicode字符集是两个不同的主体分别发布的标准。当然,后者的英文为Unicode Character Set,缩写同样是UCS

3. Unicode编码模型

Unicode编码模型

层次

层次名称

作用

结果

第一层

抽象字符表ACR

字符范围

 

第二层

编号字符集CSS

字符编号

Unicode字符集

第三层

字符编码方式CEF

码元序列

UTF-8, UTF-16

第四层

字符编码方案CES

物理编码(确定字节序)

字节序列

第五层

传输编码语法TES

网络传输编码

base64

层次

层次名称

作用

结果

第一层

抽象字符表ACR

字符范围

第二层

编号字符集CSS

字符编号

Unicode字符集

第三层

字符编码方式CEF

码元序列

UTF-8, UTF-16

第四层

字符编码方案CES

物理编码(确定字节序)

字节序列

第五层

传输编码语法TES

网络传输编码

base64

以上5个层次被称为Unicode编码模型,其实也是Unicode编码实现的步骤。

(1)第一层:抽象字符表ACR(Abstract Character Repertoire)

ACR用于确定可以编码的字符的范围(即,确定支持哪些字符) 字符表分为是封闭的字符表和开放的字符表,封闭的字符表不允许添加新的字符,比如ASCII字符表;开放的字符表允许不断的添加新的字符,Unicode字符表就是开放字符表,另外,代码页在一定程度上也是开放的。

(2)第二层:编号(编码)字符集CSS(Coded Character Set)

为每个字符编一个唯一的编号,从而形成一个庞大的“字符编号对”的集合,这个集合就是编号字符集CSS。比如,将大写字母A编号为整数65,B编号为66等,注意:Unicode字符的编号是使用16进制数表示的。需要注意的是,编号字符集仅仅规定了每个字符的编号,并未将编号转换为二进制串。

Coded Character Set通常翻译为“编码字符集”,但由于此步骤的特征,翻译为“编号字符集”更为贴切,还可避免与之后转换为二进制时的“编码”相混淆。

Unicode用数字0-0x10FFFF来映射这些字符,最多可以容纳1114112个字符,或者说有1114112个码位。

(3)第三层:字符编码方式/格式CEF(Character Encoding Form)

在Unicode字符编码模型中,编码格式(encoding form)指定如何将每个码点表示为一个或多个编码单元序列。Unicode标准提供了三种不同的编码格式,使用8位、16位和32位编码单元,分别为UTF-8、UTF-16、UTF-32。

UTF全称:Unicode Transformation Format(Unicode转换格式),UTF-8、UTF-16、UTF-32都是将数字(码点)转换到程序数据(码元序列)的编码格式

UCS在编码上也有自己的格式:UCS-2和UCS-4等等。

(4)第四层:字符编码方案CES(Character Encoding Scheme)

将逻辑上的码元序列映射为物理上的字节序列(即,物理字符编码),字节序列仍是一个二进制串,此步骤的主要目的是确字码元序列的字节序,字节序确定之后就可以直接由计算机处理、存储了,由于UTF-8编码不存在字节序问题,所以使用UTF-8编码的字符不需要经过此层。

对于UTF-16和UTF-32,字节串行化规范必须考虑当前表示数据的系统采用的是big-endian(大端法)还是little-endian(小端法)结构。因此,Unicode标准中定义的三种编码格式,导致总共七种Unicode编码方案,分别为:UTF-8、UTF-16、UTF-16BE、UTF-16LE、UTF-32、UTF-32BE、UTF-32LE。 必须明确,字符编码格式(character encoding form)指在内存或API中的整数数据单元,与字节顺序不相关;字符编码方案(character encoding scheme)指字节串行化的数据,如I/O流或者文件,必须制定字节顺序。

(5)第五层:传输编码语法TES(Transfer encoding Syntax)

将字节序列进一步编码处理,以适合于在网络中传输。

由于历史的原因,在某些特殊的传输环境中,需要对上一层次的字符编码模式CES所提供的字节序列(字节流)作进一步的适应性编码处理。一般包括两种:

① 一种是把字节序列映射到一套更受限制的值域内,以满足传输环境的限制,例如用于Email传输的Base64编码或者quoted-printable编码(可打印字符引用编码),都是把8位的字节映射为7位长的数据。

注:Email协议设计为仅能传输7位的ASCII字符;从一个8位字节的角度来看,ASCII字符的首位始终为0,所以除去首位的0,实际有效的位数为7位,或许最初是出于节约传输流量的考虑,Email协议被设计为了仅能传输7位的ASCII字符。

② 另一种是压缩字节序列的值,如LZW或者进程长度编码等无损压缩技术。

4. UTF-32与UCS-4

在Unicode与ISO 10646合并之前,ISO 10646标准为“通用字符集”(UCS)定义了一种31位的编码形式(即UCS-4),其编码固定占用4个字节,编码空间为0x00000000~0x7FFFFFFF(可以编码20多亿个字符)。UCS-4有20多亿个编码空间,但实际使用范围并不超过0x10FFFF,并且为了兼容Unicode标准,ISO也承诺将不会为超出0x10FFFF的UCS-4编码赋值。由此UTF-32编码被提出来了,它的编码值与UCS-4相同(UTF-32/UCS-4编码单元的值也与Unicode码点的值完全相同),只不过其编码空间被限定在了0~0x10FFFF之间。因此也可以说:UTF-32是UCS-4的一个子集。

5. UTF-16与UCS-2

除了UCS-4,ISO 10646标准为“通用字符集”(UCS)定义了一种16位的编码形式(即UCS-2),其编码固定占用2个字节,它包含65536个编码空间(可以为全世界最常用的63K字符编码(例:“汉”的UCS-2编码为6C49)。为了兼容Unicode,0xD800-0xDFFF之间的码位未使用)。

但俩个字节并不足以正真地“一统江湖”(a fixed-width 2-byte encoding could not encode enough characters to be truly universal),于是UTF-16诞生了,与UCS-2一样,它使用两个字节为全世界最常用的63K字符编码,不同的是,它使用4个字节对不常用的字符进行编码。UTF-16属于变长编码。因此,UCS-2是UTF-16的一个子集。

6. UTF-8

为满足基于ASCII,面向字节的系统的需要,Unicode标准中定义了第三种编码格式UTF-8。它是一种使用8位编码单元的变宽的编码格式。

在UTF-8的编码单元种,一些高位用于指示当前字节在编码单元序列中的那一部分。8位编码单元的取值的一部分范围保留给UTF-8的编码单元序列的首字节;另一部分完全奋力的范围保留给序列中的后续字节,以保证UTF-8不重叠。

UTF -8编码格式对所有ASCII码点具有透明性。在U+0000到U+007F范围内的Unicode码点,被转换为UTF-8中单一的字节0x00到 0x7F,与ASCII码没有区别。并且,从0x00到0x7F不会出现在其他Unicode码点的UTF-8表示中的任一字节中,保证了不存在歧义。 Unicode中超出ASCII范围位于U+0080到U+07FF的其他一些非表意字母使用两个字节表示;位于U+0800到U+FFFF范围内的非代理码点使用三字节表示;超出U+FFFF的增补码点则需要四字节表示。

字节数

Unicode

UTF-8编码

1

000000-00007F(0-7)

0xxxxxxx(7)

2

000080-0007FF(8-11)

110xxxxx 10xxxxxx(11)

3

000800-00FFFF(12-16)

1110xxxx 10xxxxxx 10xxxxxx(16)

4

010000-10FFFF(17-21)

11110xxx 10xxxxxx 10xxxxxx 10xxxxxx(21)

字节数

Unicode

UTF-8编码

1

000000-00007F(0-7)

0xxxxxxx(7)

2

000080-0007FF(8-11)

110xxxxx 10xxxxxx(11)

3

000800-00FFFF(12-16)

1110xxxx 10xxxxxx 10xxxxxx(16)

4

010000-10FFFF(17-21)

11110xxx 10xxxxxx 10xxxxxx 10xxxxxx(21)

UTF-8是Internet中HTML和类似协议偏好的编码格式。 UTF-8同其他的多字节编码方式相比具有以下特点:

a) UTF-8的编码单元序列的第一个字节指明了后面所跟的字节的数目。对前向解析非常有效。多字节编码(N>1个字节):第一个字节的前N位都为1,第N+1位为0,后面N-1 个字节的前两位都为10,这N个字节中其余位全部用来存储Unicode中的码位值。

b) 从UTF-8字节流的任意位置开始可以有效的找到一个字符的起始位置。

c) UTF-8中不存在字节取值的重叠。

参考

  • unicode编码对照表(unicode编码占几个字节) – 聚集快讯 – 聚集号 (msheying.com)
  • Unicode, UTF-8, UTF-16, UTF-32, UCS-2, UCS-4是什么?_Jonny Z的博客-CSDN博客_ucs4