`
laughingchs
  • 浏览: 68078 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

代码点、字符编码小记

 
阅读更多

代码点、字符编码方案、UTF-16:这些是指什么?

字符集是字符的集合。例如,汉字字符是中国人最先发明的字符,在中文、日文、韩文和越南文的书写中使用。

编码字符集是一个字符集,它为每一个字符分配一个唯一数字。Unicode 标准的核心是一个编码字符集,字母“A”的编码为 004116 和字符“€”的编码为 20AC16。Unicode 标准始终使用十六进制数字,而且在书写时在前面加上前缀“U+”,所以“A”的编码书写为“U+0041”。

代码点是指可用于编码字符集的数字。编码字符集定义一个有效的代码点范围,但是并不一定将字符分配给所有这些代码点。有效的 Unicode 代码点范围是 U+0000 至 U+10FFFF。Unicode 4.0 将字符分配给一百多万个代码点中的 96,382 代码点。

字符编码方案是从一个或多个编码字符集到一个或多个固定宽度代码单元序列的映射。最常用的代码单元是字节,但是 16 位或 32 位整数也可用于内部处理。UTF-32、UTF-16 和 UTF-8 是 Unicode 标准的编码字符集的字符编码方案。

UTF-32 即将每一个 Unicode 代码点表示为相同值的 32 位整数。很明显,它是内部处理最方便的表达方式,但是,如果作为一般字符串表达方式,则要消耗更多的内存。

UTF-16 使用一个或两个未分配的 16 位代码单元的序列对 Unicode 代码点进行编码。值 U+0000 至 U+FFFF 编码为一个相同值的 16 位单元。增补字符编码为两个代码单元,第一个单元来自于高代理范围(U+D800 至 U+DBFF),第二个单元来自于低代理范围(U+DC00 至 U+DFFF)。这在概念上可能看起来类似于多字节编码,但是其中有一个重要区别:值 U+D800 至 U+DFFF 保留用于 UTF-16;没有这些值分配字符作为代码点。这意味着,对于一个字符串中的每个单独的代码单元,软件可以识别是否该代码单元表示某个单单元字符,或者是否该代码单元是某个双单元字符的第一个或第二单元。这相当于某些传统的多字节字符编码来说是一个显著的改进,在传统的多字节字符编码中,字节值 0x41 既可能表示字母“A”,也可能是一个双字节字符的第二个字节。

UTF-8 使用一至四个字节的序列对编码 Unicode 代码点进行编码。U+0000 至 U+007F 使用一个字节编码,U+0080 至 U+07FF 使用两个字节,U+0800 至 U+FFFF 使用三个字节,而 U+10000 至 U+10FFFF 使用四个字节。UTF-8 设计原理为:字节值 0x00 至 0x7F 始终表示代码点 U+0000 至 U+007F(Basic Latin 字符子集,它对应 ASCII 字符集)。这些字节值永远不会表示其他代码点,这一特性使 UTF-8 可以很方便地在软件中将特殊的含义赋予某些 ASCII 字符。

下表所示为几个字符不同表达方式的比较:

Unicode 代码点 U+0041 U+00DF U+6771 U+10400
表示字形        
UTF-32 代码单元
00000041
000000DF
00006771
00010400
UTF-16 代码单元
0041
00DF
6771
D801 DC00
UTF-8 代码单元
41
C3 9F
E6 9D B1
F0 90 90 80

为了提高计算机的信息处理和交换功能,使得世界各国的文字都能在计算机中处理,从1984年起,ISO组织就开始研究制定一个全新的标准:通用多八位编码字符集(Universal Multiple-Octet Coded Character Set),简称UCS。标准的编号为:ISO 10646。这一标准为世界各种主要语言的字符(包括简体及繁体的中文字)及附加符号,编制统一的内码。

统一码(Unicode)是Universal Code的缩写,是由另一个叫Unicode学术学会The Unicode Consortium)的机构制定的字符编码系统。UnicodeISO 10646国际编码标准从内容上来说是同步一致的。

UnicodeJava语言和XML的基础,所以我们要稍微详细地介绍一下Unicode以及ISO 10646标准。

注意

不够耐心的读者可以跳过本章的余下部分。但显然了解本章所描述的Unicode及相关编码的技术细节,有利于你更好地理解和应用Unicode

UnicodeISO 10646的关系

1991年,Unicode学术学会与ISO国际标准化组织决定共同制订一套适用于多种语言文本的通用编码标准。UnicodeISO 10646国际编码标准于19921月正式合作发展一套通用编码标准。自此,两个组织便一直紧密合作,同步发展UnicodeISO 10646国际编码标准。

ISO 10646UCS

Unicode

1993年,ISO组织发表ISO 10646国际编码标准的第一个版本,全名是ISO/IEC 10646-1:1993。它收录了20902个表意字符(ideograph,中日韩文均属表意字符)。

同年,Unicode学术学会根据ISO/IEC 10646-1:1993修订了Unicode 1.0,发布Unicode 1.1

不断改善和修订ISO 10646标准。

1996年发表Unicode 2.01998年发表Unicode 2.1,根据ISO 10646做了一些改善和修订,新增了欧元符号。

200010月发表了ISO 10646第二版的第一部分:ISO/IEC 10646-1:2000,新增收了6,582个表意字符于扩展区A中(CJK Unified Ideographs Extension A)。

20002月,发表Unicode 3.0,也包含了同样的CJK Ext A

2001年,发表了ISO/IEC 10646的第二部分,增收了42711个表意字符于扩展区B里。

2001年,Unicode发表3.1版,将CJK Ext B纳入新版Unicode中。

虽然两个组织保持如此密切的合作关系,但UnicodeISO 10646还是有区别的。ISO 10646着重定义字符编码,而Unicode则在此基础上,为这些字符及编码数据提出应用的方法以及对语义数据作补充。

UCS的结构

UCS的结构是一个四维的编码空间,每一维由一个字节(八位二进制位)组成,范围是00FF。总体上分为128个群组(Group 00-7F),每一群组由256个平面(Plane 00-FF)组成,每一平面有256(Row 00-FF),每一行256个编码位(Cell 00-FF)。所以,每一平面包括65,536个字符位(Character Position 0000-FFFF)

整个编码字符集的每个字符都由4个字节,按---的顺序表示。所以UCS的可编码空间为:128 × 256 × 256 × 256 = 231

UCS将其第一个平面(00群组中的00平面)称作基本多语种平面(Basic Multilingual PlaneBMP)。

image003.jpg

UCS中,目前只有00组是重要的,Unicode学术学会断言,在可以预见的将来,甚至不可能用完00组中的前17个平面(00平面到10平面)。因此,Unicode只定义了ISO 10646的第00组的前17个平面。事实上,目前绝大多数字符,都分配在第00平面BMP中。

image004.jpg

下表中列出了BMP中的字符分配情况:

区间

描述

0000-1FFF)基本拼音字符区

包括所有拼读文字的字母拼音和音标。它的字符集一般较小,如:拉丁文、西里尔文、希腊文、希伯来文、阿拉伯文、泰文、天成文书(梵文)等。

2000-28FF)符号区

包括许多种用于标点、数学、化学、科技及其它特殊用途上的符号丁贝符(示意图形符号)。

2E80-33FF)中日韩语音及符号区

包括用于中国、日本、韩国语言中的标点、符号、字根(笔画)及发音等字符。

3400-9FA5)中日韩汉字字符区

27,484个中日韩(越)的统一汉字组成。

A000-A4C6)彝族字符区

1,165个中国南方彝族音节和50个其字根组成。

AC00-D7A3)韩字符拼音区

11,172个预先组合的韩字符拼音音节组成。

D800-DFFF)代理区

这个区被平分为1024高半代理区D800-DBFF)码位和1024低半代理区DC00-DFFF)码位,用来形成代理对,可以得到超过一百万个扩充编码位。

E000-F8FF)私人专用区

包含6,400个编码位,用于用户或开发商自行定义的字符编码。

F900-FA2D)兼容字符区

包括一些被许多行业协会和国家标准广泛使用的字符,但在Unicode编码中有不同的表现形式。包含一些专用字符。

UCS的表现形式

UCS有两种方式来表示一个字符编码:四字节正规形式(UCS-4Four-octet canonical form)和双字节基本平面形式(UCS-2Two-octet BMP form)。

UCS-4 —— 四字节正规形式

UCS-44个字节来表示一个字符。第一个字节表示组(Group),第二表示平面(Plane),第三表示行(Row),第四表示单元号或列(Cell)。

UCS-2 —— 双字节基本平面形式

当系统只使用BMP的字符码时,可以省略群组和平面中的八位,将字符码由32个位缩短为16个位(2个字节)。标记为UCS-2

UnicodeUCS-2同样采用16位编码。所以一般可以把UnicodeUCS-2看作是同一样东西

代理对(Surrogate Pair

UCS-4定义了4个字节表示一个字符,用来应付将来的扩展是绰绰有余。可是UnicodeUCS-2只定义了2个字节,却很容易用尽。代理对(Surrogate Pair)的设计在这种背景下应运而生。

UCS-2BMP中开辟了一个特殊的区间(D800 - DFFF -- 代理区,并平分成两个区,分别称为高半代理区(High-half ZoneD800 - DBFF),和低半代理区(Low-half ZoneDC00 - DFFF),各有1024个码位。使用时,从高低两个代理区中各取一个编码组成一个四字节的代理,来表示一个在BMP以外平面上的编码字符位。这样一来,总共可以多表示1024×1024个字符,映射到00群组中的0110平面(共16个平面)。

代理对提供了用BMP2字节编码来表示在基本多文种平面(BMP)之外的16个平面编码的机制。一些不常用的字符可以用代理对表示。目前,只有ISO/IEC 10646-2:2001Unicode 3.1才使用到代理对。

高半代理区和低半代理区的划分,使编码位相互区分开。非代理区字符一定不会在这个区里。因为高半代理区和低半代理区不相交,所以很容易决定字符值的边界。一个完好的文本中,高半代理码和低半代理码总是按先后成对出现。

如果在实现上没有删除代理码或在代理码对中插入字符,数据的完整性就可得到保证。即使数据有残损,也只是局部的。一个残缺的码只影响一个字符。因为高半代理区和低半代理区不相交,且成对出现,错码不会传到文本的其它部分。

具体来说,一个代理对(HL)由码值为D800-DBFF 的高半代理码H和码值为 DC00-DFFF低半代理码L组成。将一个字符映射到UCS-4码位中。假设NUCS-4码值,则有:(以下所有数字均为16进制)

N = (H - D800) × 400 + (L - DC00) + 10000

于是得到N的码值为1000010FFFF

注意

Unicode 3.0没有用到代理对,直到3.1才增加了CJK Ext B,用到了02平面,需要使用代理对才能访问。但99.99%的情况下,根本用不到那些字。此外,JDK1.4只支持到Unicode 3.0,所以目前Java还不能应用代理对。

UTF编码

UTFUCS Transformation Format的缩写,意为UCS转换格式UCS只是一个字形和内码上的标准,并没有定义实际在计算机上存取的方法,而UTF便定义了一整套的计算机存取UCS编码的转换格式,并考虑了与其它编码方式兼容。常用的格式有UTF-8UTF-16。有时也用到UTF-7来进行7位数据传输。

UTF-16

UTF-16是用定长16位(2字节)来表示的UCS-2Unicode转换格式。它将Unicode的编码值变成2字节的Big-endian(高位字节在前,低位字节在后)或Little-endian(低位字节在前,高位字节在后)编码。UTF-16利用代理对来访问BMP之外的字符编码。

Java使用Big-endian系统,而Intel系列处理器内部使用Little-endian系统(学汇编语言和C语言的人都知道)。

例如:中国两字,Unicode4E2D 56FD,在Windows上用UTF-16编码,结果为四个字节:2D 4E FD 56;如果使用Java输出,结果为:4E 2D 56 FD

使用UTF-16有什么缺点呢?很显然,

1.   所有原本1个字节就可以表示的西方字符,现在要用2个字节来表示,体积大了一倍。

2.   学过C的人都知道,0x00代表C字符串的结尾。但是用UTF-16来表示单字节字符(ISO-8859-1)时,高位字节为0x00。这样就会使C语言库函数发生误判。用UTF-16表示文件名、网址等,全引出无数的问题。

3.   字符的边界不好找。程序处理时必须从字符串的头部开始扫描,才可能正确地找出一个字符的边界,效率较低。此外,万一坏掉一个字节,这个字节之后的字符都会错位,坏掉一片。

所有的这些问题,在UTF-8中都不存在。

但是,UTF-16也有其天然的优点:它直接表现了字符编码的整数值。所以UTF-16是最直接的Unicode表示法。此外,它是定长的,这大大简化了字符串的操作。Java语言就是用UTF-16格式将字符存储在内存中的。正是这样,才使JavaUnicode字符串的操作格外简单高效。

UTF-8

UTF-8使用了变长技术,在每一个编码区域有不同的字码长度:

1.   UCS-2,由1字节至3字节构成;

2.   如果UCS-2使用了代理对,则UTF-8最长可到4字节;

3.   UCS-4,由1字节至6字节构成。

因为以字节(8位)为组成单元,故称为UTF-8。对于英文文本,UTF-8的文件大小比其它转换格式都小。

UTF-8内,字符由1个至6个字节为组合。下表列举出了不同范围的UCS码转换成UTF-8的规则。英文字母“x”代表可以用来记录 Unicode 码值的区域。

UCS-4 区域(十六进制)

UTF-8字节组合(二进制)

0000 0000 —— 0000 007F

0xxxxxxx

0000 0080 —— 0000 07FF

<span

分享到:
评论
发表评论

文章已被作者锁定,不允许评论。

相关推荐

Global site tag (gtag.js) - Google Analytics