精华内容
下载资源
问答
  • 字符编码标准

    2015-08-19 00:00:16
    前几天看文初的《精武门之Web安全研讨会首日感受》,说到利用字符集攻击时提到以前宝宝写的一篇有关国际化的文章,趁机再次拜读了宝宝的这篇大作,不得不感慨宝宝的写作功底,无敌!这么好的文章不分享出来实在是太...

    前几天看文初的《精武门之Web安全研讨会首日感受》,说到利用字符集攻击时提到以前宝宝写的一篇有关国际化的文章,趁机再次拜读了宝宝的这篇大作,不得不感慨宝宝的写作功底,无敌!这么好的文章不分享出来实在是太可惜了,在此将宝宝的大作转帖于此;

    作者序

    在我开发Java程序的几年中,遇到得最多,也是别人向我提问最多的问题,就是各种各样看似稀奇古怪的中文乱码问题了。网上也有许多解释和解决Java中文问题的文章,但水平参差不齐,有一些文章甚至是错误的。

    此外,我们公司自己的Java程序从一开始就采用了错误的方式处理中文问题,虽能解一时之急,却引出了越来越多的深远的问题。每当我听到有的同事还在讨论如何特殊处理双字节的中文GB码,就感慨他们思路的狭隘。试问,今天我们可以用特殊的方式处理我们所熟悉的中文编码,可是今后我们怎样才能应付日文版、韩文版、或世界其它国家语言的产品开发呢?

    在我看来,与其说这些问题是“中文化问题”,不如说是“国际化问题”。所谓的“汉化”这种说法已经随时代远去了。想想看,这个词带有明显的小农经济的色彩:自家汉化自家用,哪管世界变化多。经过汉化的软件,常常意味着:版本落后、不兼容、不稳定。为什么会这样呢?根本原因是,从软件的设计阶段,就没有考虑国际用户的需要,没有采用国际通用的标准。事后要弥补自然难上加难。

    所以让我们把眼光放开,想一想“国际化”。当然国际化的目的还是生产出“汉化”的软件,但我们可以用同样的方法“韩化”、“日化”、“阿拉伯化”,统称为“本地化” —— 这就是“国际化”的目的。国际化和本地化有两个很体面的英文缩写:I18n(Internationalization)和L10n(Localization)。

    想要开发出国际化的软件产品,首先要了解国际标准,而不是使用东拼西凑的权宜之计。本文首先从相关国际标准的讨论切入,相信正确地理解和应用这些标准,所有的“中文化问题”或“国际化问题”都会迎刃而解。

    字符编码简介

    ASCII码

    从学计算机的那天开始,老师就告诉我们在计算机里面,所有的英文字母都对应到一个数字编码,这就是ASCII码(American Standard Code for Information Interchange)。ASCII码是很久很久以前(1968年)制定的。它只使用了一个8位字节中的低7位,总共是127个编码位。这样的方案很快就不够使用了。

    单字节编码的发展

    在80年代早期,一些现在流行的标准(如ISO 8859Unicode)还未出现。那时为了支持多种地区的语言,各大组织机构或IT厂商开始发明它们自己的编码方案,以便弥补ASCII编码的不足。一时间,各种互不相容的字符编码方案成百花齐放之势。

    为了避免混乱,ISO组织在1998年之后,陆续发表了一系列代号为8859的标准,作为ASCII编码的标准扩展,终于统一了单字节的西方字符的编码。ISO是设在瑞士的国际标准化组织的简称(International Organization for Standardization)。

    ISO-8859-1(Latin1 - 西欧字符)

    ISO-8859-1覆盖了大多数西欧语言,包括:法国、西班牙、葡萄牙、意大利、荷兰、德国、丹麦、瑞典、挪威、芬兰、冰岛、爱尔兰、苏格兰、英格兰等,因而也涉及到了整个美洲大陆、澳大利亚和非洲很多国家的语言。

    此外,ISO-8859-1后来被采纳为ISO-10646标准(后面会讲到)的首页,换句话说,Unicode的最开头256个字符编码和ISO-8859-1是一一对应的。正是由于这个特殊性,使很多人产生了对ISO-8859-1编码的误用。

     

     

    ISO-8859标准还包括:

    • ISO-8859-2(Latin2 - 中、东欧字符)
    • ISO-8859-3(Latin3 - 南欧字符)
    • ISO-8859-4(Latin4 - 北欧字符)
    • ISO-8859-5(Cyrillic - 斯拉夫语)
    • ISO-8859-6(Arabic - 阿拉伯语)
    • ISO-8859-7(Greek - 希腊语)
    • ISO-8859-8(Hebrew - 希伯来语)
    • ISO-8859-9(Latin5)
    • ISO-8859-10(Latin6)
    • ISO-8859-11(Thai - 泰国语)
    • ISO-8859-12(保留)
    • ISO-8859-13(Latin7)
    • ISO-8859-14(Latin8)
    • ISO-8859-15(Latin9)

    但是ISO 8859系列标准的字符编码,还是互不相容,不可能同时使用的。毕竟它们只是单字节的编码方案。而且,它们和多字节的编码方案如中文编码GB2312BIG5也是不相容的。那些欧洲字符(最高位为1的字符),在GB2312BIG5中被认为是双字节汉字编码的首字节。

    多字节编码的发展

    单字节编码只有256个码位(28=256),而中文字符何止千千万,单字节编码不可能满足中文编码的需要。于是为了适应东方文字信息处理的需要,ISO又制定了ISO 2022标准(Character code structure and extension techniques),提供了七位与八位编码字符集的扩充方法的标准。我国根据ISO 2022制定了国家标准GB2311 ——《信息交换用七位编码字符集的扩充方法》,并根据该标准制定了国家标准GB2312-80编码。其他东方国家和地区也制定了各自的字符编码标准,如日本的JIS0208,韩国的KSC5601,台湾地区的CNS11643等。

    BIG5

    BIG5是从CNS11643的早期版本发展而来的,虽然没有包括CNS11643的全部内容,但却是目前台湾、香港地区普遍使用的一种繁体汉字的市场标准,包括440个符号,一级汉字5401个、二级汉字7652个,共计13060个汉字。

    GB2312-80

    全称是《信息交换用汉字编码字符集 基本集》,1980年发布,是中文信息处理的国家标准,在大陆及海外使用简体中文的地区(如新加坡等)是强制使用的唯一中文编码。

    他由6763个常用汉字和682个全角的非汉字字符组成。其中汉字根据使用的频率分为两级。一级汉字3755个,二级汉字3008个。由于字符数量比较大,GB2312采用了二维矩阵编码法对所有字符进行编码。首先构造一个94行94列的方阵,对每一行称为一个“区”,每一列称为一个“位”,然后将所有字符依照下表的规律填写到方阵中。这样所有的字符在方阵中都有一个唯一的位置,这个位置可以用区号、位号合成表示,称为字符的区位码。如第一个汉字“啊”出现在第16区的第1位上,其区位码为1601。因为区位码同字符的位置是完全对应的,因此区位码同字符之间也是一一对应的。这样所有的字符都可通过其区位码转换为数字编码信息。GB2312字符的排列分布情况如下: 

    分区范围 符号类型
    第01区 中文标点、数学符号以及一些特殊字符
    第02区 各种各样的数学序号
    第03区 全角西文字符
    第04区 日文平假名
    第05区 日文片假名
    第06区 希腊字母表
    第07区 俄文字母表
    第08区 中文拼音字母表
    第09区 制表符号
    第10-15区 无字符
    第16-55区 一级汉字(以拼音字母排序)
    第56-87区 二级汉字(以部首笔画排序)
    第88-94区 无字符
    GB2312字符在计算机中存储是以其区位码为基础的,其中汉字的区码和位码分别占一个存储单元,每个汉字占两个存储单元。由于区码和位码的取值范围都是在1-94之间,这样的范围同西文的存储表示冲突。例如汉字‘珀’在GB2312中的区位码为7174,其两字节表示形式为71,74;而两个西文字符‘GJ’的存储码也是71,74。这种冲突将导致在解释编码时到底表示的是一个汉字还是两个西文字符将无法判断。为避免同西文的存储发生冲突,GB2312字符在进行存储时,通过将原来的每个字节第8bit设置为1同西文加以区别,如果第8bit为0,则表示西文字符,否则表示GB2312中的字符。实际存储时,采用了将区位码的每个字节分别加上A0H(160)的方法转换为存储码,计算机存储规则是此编码的补码,而且是位码在前,区码在后。例如汉字‘啊’的区位码为1601,其存储码为B0A1H,其转换过程为:
    区位码 区码转换 位码转换 存储码
    1001H 10H+A0H=B0H 01H+A0H=A1H B0A1H

    ·         双字节编码,范围:B0A0 ~ F7FE(首字节在B0-F7 之间,尾字节在A0-FE 之间)。

    GBK

    汉字内码扩展规范(GBK)是国家技术监督局1995年为中文Windows 95所制定的新的汉字内码规范。

    ·         双字节编码,GB2312-80的扩充,在码位上和GB2312-80兼容。

    ·         范围:8140 ~ FEFE(首字节在81-FE 之间,尾字节在40-FE 之间,剔除xx7F)共23940个码位。

    ·         包含21003个汉字,包含了ISO 10646中的全部中日韩汉字,简、繁体字融于一库。

    严格说,GBK不能算是国家标准,最多算是一个商业标准。而GB18030才是真正的国家标准。

    GB18030-2000

    全称是《信息交换用汉字编码字符集》,是我国的强制标准,所有不支持GB18030标准的软件将不能作为产品出售。

    ·         单字节、双字节、四字节编码。

    ·         向下与GB2312编码兼容。

    ·         支持GB 13000.1-1993中的全部中、日、韩(CJK)统一汉字字符和全部CJK统一汉字扩展A的字符。

    虽然GB18030标准非常强大,但它是一个中国大陆的标准。在编码上,除了和GB2312以外,还是不能和世界上其它任何一种字符编码统一。

    终极标准 —— Unicode和ISO 10646

    前面所讲的一切字符编码方案,都是针对局部地区或少数语言文字的,没有办法同时表达所有的语言文字,或在多种语言平台上交换。这对今天极其频繁的国际信息交流是不相称的。

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

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

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

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

    Unicode和ISO 10646的关系

    在1991年,Unicode学术学会与ISO国际标准化组织决定共同制订一套适用于多种语言文本的通用编码标准。UnicodeISO 10646国际编码标准于1992年1月正式合作发展一套通用编码标准。自此,两个组织便一直紧密合作,同步发展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.0,1998年发表Unicode 2.1,根据ISO 10646做了一些改善和修订,新增了欧元符号。

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

    2000年2月,发表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的结构是一个四维的编码空间,每一维由一个字节(八位二进制位)组成,范围是00到FF。总体上分为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 Plane,BMP)。

     

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

     

    下表中列出了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-4,Four-octet canonical form)和双字节基本平面形式(UCS-2,Two-octet BMP form)。

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

    UCS-4用4个字节来表示一个字符。第一个字节表示组(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 Zone,D800 - DBFF),和低半代理区(Low-half Zone,DC00 - DFFF),各有1024个码位。使用时,从高低两个代理区中各取一个编码组成一个四字节的代理,来表示一个在BMP以外平面上的编码字符位。这样一来,总共可以多表示1024×1024个字符,映射到00群组中的01到10平面(共16个平面)。

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

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

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

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

    N = (H - D800) × 0400 + (L - DC00) + 01 0000

    于是得到N的码值为01 0000到10 FFFF。

    注意

    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语言的人都知道)。

    例如:“中国”两字,Unicode是4E2D 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格式将字符存储在内存中的。正是这样,才使Java的Unicode字符串的操作格外简单高效。

    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

    110xxxxx 10xxxxxx

    0000 0800 —— 0000 FFFF

    1110xxxx 10xxxxxx 10xxxxxx

    0001 0000 —— 001F FFFF

    11110xxx 10xxxxxx 10xxxxxx 10xxxxxx

    0020 0000 —— 03FF FFFF

    111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx

    0400 0000 —— 7FFF FFFF

    1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx

    UTF-8内,

    1.   如果一个字节,最高位(第8位)为0,表示这是一个ASCII字符(00 - 7F)。可见,所有ASCII编码已经是UTF-8了。

    2.   如果一个字节,以11开头,连续的1的个数暗示这个字符的字节数,例如:110xxxxx代表它是双字节UTF-8字符的首字节。

    3.   如果一个字节,以10开始,表示它不是首字节,需要向前查找才能得到当前字符的首字节。

    可见UTF-8可以有效地保证数据的完整性,避免出现编码的错位。即使偶然出现“坏字”,也不会影响到后续的文本。

    那么UTF-8有什么缺点呢?显然,对于在BMP中的中文字来说,需要用3个字节才能表示,比使用UTF-16或直接使用双字节的GB2312编码大了0.5倍。

     

    上文说了一大通,总结一下,其实很简单:

    1. 字符编码是抽象字符在计算机中的数字表示。
    2. 字符编码集(character set,简称字符集)是一批字符编码的集合。世界上存在大量互不兼容的字符集,给国际交流带来了困难。
    3. ASCII码是最古老的字符编码,它总共只定义了7位共128个字母、数字和符号。但它是其它所有字符编码的基础。
    4. Unicode用16位整数编码,将世界上所有主要文字的字符统一起来了。如果利用代理对(surrogate pair)最多可以表示从00 0000到01 FFFF的字符。然而绝大多数情况下,只需要用到0000到FFFF之间的字符就足够了。
    5. Unicode常用UTF-8UTF-16来表示。7位的ASCII码不用作任何变化,就已经是UTF-8了。但UTF-8需要用3个字节来表示一个汉字。
    6. ISO 8859系列字符集,定义了单字节字符编码的标准。其中最特殊的是ISO-8859-1编码,它的编码和Unicode中最开始的256个字符编码完全相同。
    7. GB18030编码是中国大陆的国家标准,在字汇上等同于Unicode,在编码上和GB2312编码以及GBK编码兼容。

    更详细介绍,请参阅:http://blog.csdn.net/rainday0310/article/details/8494808
    展开全文
  • Unicode字符编码标准

    千次阅读 2018-08-16 16:46:05
    Unicode ...如何解释这些整数是由字符集(character set)、编码(encoding)决定的。  文 本主要是由字符(character)组成。在格式文本(fancy text, or rich text)中包括显示属性,如颜色、斜...

    Unicode

    1. 编码知识 
    1.1 文本和字符 
    在计算机程序中或者数据文件里,文本(text)是作为数字序列存储的。序列中的数字是具有不同大小、取值和解释的整数。如何解释这些整数是由字符集(character set)、编码(encoding)决定的。 
    文 本主要是由字符(character)组成。在格式文本(fancy text, or rich text)中包括显示属性,如颜色、斜体字、上标等,但仍然是以字符组成的纯文本(plain text)为基础的。有时,格式文本与纯文本之间的区别很复杂,依赖于具体的应用。 
    什么是字符?典型地,是字母。也可以是数字、句点、连字号、标点符号和数学符号,对于中文,也可以是汉字。还包括定义行尾和段落等的控制字符(一般不可见)。 
    有了字符,就可以为它们分配数字编码。为字符分配什么数字值,依赖于具体情况。一个简单的字符,如字母"a",在不同的程序或者数据文件中可能具有不同的整数值。 
    1.2 字符集:具有数字编码的字符 
    在信息处理中,所使用的整数总有上限,依赖于存储整数的位的数目。这也决定了可以同时区分的字符的数量。 
    在设计字符集时,首先要决定所需字符的数目,并确定所需字符的清单。根据字符的数目,可以设定整数值的上限,这个整数范围称为编码空间(code space),其中的一个特定整数称为一个码点(code point)。 
    然后,为字符清单中的每个字符指定一个整数值,也就是一个码点。这样就得到一个字符集,称作编码字符集(Coded Character Set)。 
    1.3 编码单元、字节和编码 
    在 计算机系统的实现中,整数以特定大小的单元表示,通常为8位(1字节),16位,或32位。在字符编码中,这样的单元称为编码单元(code unit)。根据编码空间的大小和具体要求,来选择合适的编码单元。通常,所选择编码单元对应的整数范围要大于编码空间的整数范围,这样每个码点就只需一 个编码单元表示,并且在字符码点与编码单元间的转换非常简便,因为字符码点对应的整数值与相应编码单元的整数值相同。如果编码单元对应的整数范围小于编码 空间的整数范围,就需要多个编码单元表示一个码点。 
    字节是计算机系统中最基本的表示单元,无论是存储在内存中,还是将文本写入文件或通过网络发送,总是要读写若干字节。因此,在实际应用中,还需要将编码单元进一步表示为字节序列。 
    将字符表示为字节序列的过程就称为编码(encoding),更重要的是,还包括如何对字节序列进行解释以取得字符。 
    1.4 不同的字符集 
    在一些常用的编码中,每个字符只使用一个字节表示,称单字节字符集(single-byte character set, SBCS)。这些字符集都仅限于256个字符。 
    在ASCII之后,目前应用最广泛的单字节字符集是ISO-8859-1。它是ASCII的一个8位超集,并且提供西欧语言所需的大多数字符。它的一个改进的版本,ISO-8859-15,还包括新的欧元符号和更多的一些法语和芬兰语字母。 
        双字节字符集(double-byte character set, DBCS)用于为东亚书写系统中所使用成千上万个表意字符提供足够空间。这里的编码仍是基于字节的,不过是两个字节一起表示一个单一的字符。 
        即使在东亚,文本中也会包含小字母表中的字母,如拉丁字母表。这些字母使用单字节表示的效率会更高。因此,提出了多字节字符集(multi-byte character set, MBDC),使用可变数目的字节来表示字符。多字节字符集通常与ASCII兼容,也就是说,在这种编码中,拉丁字母使用与ASCII中相同的字节来表示。 一些不常用的字符可能会使用三个甚至四个字节编码。 
    1.4 常见字符集 
    1.4.1 ASCII: The American Standard Code form Information Interchange 
        ASCII是一个使用7位单元的字符集,及针对7位字节的简单编码方式。尽管局限于很少的一些字符,ASCII是最重要的一种字符集,因为它是目前大多数字符集的基础。 
        ASCII只提供了128个数字值(也可称作码点,code point),其中33个被保留用作特殊功能。只有95个码点用作"真正的"文本字符。这些图形字符大多时大写和小写拉丁字母,数字和标点符号,外加一些特殊的括号、下划线和重音符号。 
    1.4.2 EBCDIC: The Extended Binary-Coded Decimal Interchange Code 
    EBCDIC是由IBM设计的编码格式,使用8位字节,被一些字符集用于大型机。EBCDIC在与ASCII相近的时期开发的,具有一些相似的特性。 
    1.4.3 Unicode 
    Unicode标准定义了一个字符集和几种编码。 
    Unicode最有吸引力的特点是它涵盖了几乎世界上的所有字符,可以只通过一个唯一的数字(Unicode码点)来访问和操作字符。 
    2. Unicode介绍 
    2.1 为什么使用Unicode? 
    在创造Unicode之前,有数百种编码系统。但是,没有任何一个编码可以包含足够的字符。例如,仅欧州共同体就需要好几种不同的编码来包括所有的语言。即使是单一的一种语言,如英语,也没有哪一个编码可以适用于所有的字母,标点符号,和常用的技术符号。 
    这些编码系统也会互相冲突。也就是说,两种编码可能使用相同的数字代表两个不同的字符,或使用不同的数字代表相同的字符。任何一台特定的计算机(特别是服务器)都需要支持许多不同的编码,但是,不论什么时候数据通过不同的编码或平台之间,那些数据总会有损坏的危险。 
    而Unicode正在改变所有这一切! 
    在Unicode标准中,提供了1,114,112个码点,不仅可以包含当今世界使用的所有语言文字和其他符号,也足够容纳绝大多数具有历史意义的古文字和符号。并且,Unicode给每个字符提供了一个唯一的数字,不论是什么平台,不论是什么程序,不论什么语言。 
    Unicode 标准已经被工业界的领导们所采用,例如: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.2 Unicode与国际化 
    直到最近,国际化的常用方法是,假定任何给定的可执行程序同时只和一种语言工作。如果在英文环境下安装,它就只处理英文文本;如果在中文环境下安装,就只处理中文文本。 
    在 这种模型下,针对不同的书写系统和语言,使用的字符集和字符编码不同。在Windows和大型机环境下,术语"代码页"(Code Page)用于描述如何将二进制值映射到人类可读得字符(字形)。一个运行的程序处在单一的代码页,该代码页确定二进制值如和与字形关联。 
    简便的国际化是Unicode的另一项优势。在内部使用Unicode的应用程序,能够同时存储和处理世界上所有的字符,这消除了传统的国际化方法所面临的一些困难。 
    当然,成功的国际化不仅仅是在应用程序中采用Unicode,还需要谨慎的屏幕布局设计(不同的语言具有不同的书写习惯)、翻译和文化理解。 
    2.3 设计原则 
    Unicode的设计反映了十大基本原则,但这些原则并不是可以同时满足。整个设计是在保证简便高效和保持与已有编码标准兼容之间的平衡。 
    (1)广泛性(Universality) 
    Unicode标准对一个单一的大字符集进行编码,包括满足世界范围需求的所有字符。 
    (2)高效(Efficiency) 
    在Unicode的字符编码模型中没有换码符(escape character),每个字符编码与其它字符编码具有相同的状态。使高效率的实现成为可能。 
    所有Unicode编码方式都是自同步的,并且相互不重叠。使在字符流中随机访问和查找操作高效。 
    同一书写字母体系中的字符被放置在一起,不仅方便字符的查找,并且使实现更紧凑压缩方法更高效。 
    (3)针对字符编码,而不是字形(Character, Not Glyph) 
    字符是书写语言中具有语义的最小组件的抽象表示。字符是以驻留在内存中的码点表示。 
    字形是字符被显示时具有的形状。与字符相比,字形出现在屏幕或纸张上作为一个或多个字符的特定表示。字形的集合构成一种字体。 
    字符和字形间存在多种关系:一个字形可以对应一个字符;一个字形也可以对应几个字符;多个字形也可能出自一个字符。 
    (4)语义(Semantic) 
    在Unicode中,字符都有明确定义的语义。字符属性表可用于解析、排序等需要有关码点语义知识的算法中。Unicode中定义的属性包括数字、间隔、组合和方向属性。 
    (5)纯文本(Plain Text) 
    纯文本或无格式文本,仅仅是字符编码的序列。纯Unicode文本就是Unicode编码的序列。而格式文本(styled text, or rich text)是由纯文本添加一些附加信息(如语言标识、字体大小、颜色等)组成的文本表示。 
    Unicode标准针对的是纯文本。 
    (6)逻辑顺序(Logical Order) 
    Unicode文本在内存表示中以逻辑顺序存储,大致对应于借助键盘输入文本的顺序。在一些情况下,当显示或打印文本时,字符顺序与逻辑顺序不同。 
    (7)统一(Unification) 
    Unicode标准为避免对字符重复编码,对不同语言书写方式中的字符进行统一,相同的字符分配唯一的一个编码。普通字母、标点符号、标记,和变音符都只分配一个编码,而不管语言;同样的还有中日韩使用的表意字符。 
    (8)动态组合(Dynamic Composition) 
    Unicode标准允许加重音符好的形式和Hangul音节的动态组合。 
    (9)等价序列(Equivalent Sequences) 
    一些文本元素即可以使用静态的预先组合好的形式,也可使用动态组合的形式。Unicode字符的不同表示序列被认为是等价的。 
    如果两个或多个序列被认为是等价的,Unicode标准不规定哪一种特定的序列是正确的,而认为每一个序列只不过与其它序列等价。 
    如 果需要一种单一的单一的表示方式,可以使用一种规范化的Unicode文本形式来减少不想要区别。Unicode标准定义了四种规范化形式: Normalization Form D (NFD),Normalization Form KD (NFKD),Normalization Form C (NFC),和Normalization Form KC (NFKC)。大约来说,NFD和NFKD将可能的字符进行分解,而NFC和NFKC将可能的字符进行组合。 
    (10)可转换性(Convertibility) 
    在Unicode 标准和其他字符集标准之间可以实现准确的转换。一般说,在其他标准中的一个码点对应于Unicode标准中一个单一的码点。然而,有时在其他标准中的一个 码点对应于Unicode标准中一个码点的序列。在Unicode文本和其他字符编码文本间的转换一般是通过明确的表映射过程完成的。 
    2.4 Unicode的码点、编码格式、编码方案 
    2.4.1 Unicode编码空间和码点 
    在Unicode标准中,编码空间的整数范围是从0到10FFFF(16进制),共1,114,112个可用的码点。 
    为了与已有的编码标准兼容,一些抽象字符可能会与多个分别编码的字符关联。而在其他一些情况下,一个抽象字符可能会用两个(或更多)编码字符序列来表示,如带重音符的字母。 
    2.4.2 Unicode编码格式 
    在Unicode字符编码模型中,编码格式(encoding form)指定如何将每个码点表示为一个或多个编码单元序列。Unicode标准提供了三种不同的编码格式,使用8位、16位和32位编码单元,分别为UTF-8、UTF-16、UTF-32。 
    (1)UTF-32 
    UTF-32是一种最简单的Unicode编码格式。每个Unicode码点被直接表示为一个32位的编码单元。UTF-32是一种固定宽度的字符编码格式。 
    每个UTF-32编码单元的值与Unicode码点的值完全相同。 
    (2)UTF-16 
    在UTF-16中,在范围U+0000到U+FFFF间的码点使用一个单一的16位编码单元表示;而,在范围U+10000到U+10FFFF间的码点则使用一对16位编码单元表示,称作代理对(surrogate pair)。 
    UTF -16优化了基本多语言平面(Basic Multilingual Plane)中字符的表示,即位于U+0000到U+FFFF范围内的字符。该范围包含了目前世界上所使用的书写系统中的绝大多数字符,每个字符只需要一 个16位的编码单元。对于基本多语言平面,UTF-16可作为固定宽度的编码格式来有效使用。 
    但对于增补字符,UTF-16需要两个16位的编码单元,意味着正式的UTF-16是一个变宽的编码格式。 
    UTF-16是早期Unicode遗留下的历史产物,原本被设计成具有固定宽度的16位编码格式。为支持超过U+FFFF的增补字符,设立了代理机制。 
    (3)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范围的其他一些非表意字母,每个都在UTF-8种使用量各字节表示;位于U+0800到U+FFFF范围内的非代理码点使用三字节表示;超出U+FFFF的增补码点则需要四字节表示。 
    UTF-8是Internet中HTML和类似协议偏好的编码格式。 
    UTF-8同其他的多字节编码方式相比具有以下特点: 
    a) UTF-8的编码单元序列的第一个字节指明了后面所跟的字节的数目。对前向解析非常有效。 
    b) 从UTF-8字节流的任意位置开始可以有效的找到一个字符的其实位置。 
    c) UTF-8中不存在字节取值的重叠。 
    2.4.3 Unicode编码方案 
    在Unicode标准中,用于Unicode数据字节串行化的各种不同类型的规范被称为Unicode编码方案(encoding scheme)。 
    在计算机系统中,大数值类型(如整型)使用多个字节表示,不同体系结构采用的字节排列顺序不同。其中,部分采用由高字节到低字节的排列顺序,称为big-endian;其他则采用由低字节到高字节的排列顺序,称little-endian。 
    对于UTF-16和UTF-32,字节串行化规范必须考虑当前表示数据的系统采用的是big-endian还是little-endian结构。 
    一个字符编码方案包括指定的字符编码格式,以及如何将编码单元串行化为字节的规范。在Unicode标准中,还规定了初始的字节顺序标志(byte order mark, BOM)的使用,用于显示区分big-endian和little-endian数据。 
    对于UTF-8,在序列中只包括UTF-8的编码单元(1字节),因此,UTF-8中的数据表示不存在字节顺序的问题。但对于16位和32位的编码方案,字节串行化过程必须将编码单元分解为两个或四个字节,并且必须清楚的定义这些字节的顺序。 
    因此,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流或者文件,必须制定字节顺序。 
    2.4.4 Unicode编码空间分配 
    根据在语言学上和功能上的类别,Unicode标准中的编码字符被分成组。 
    Unicode 编码空间的范围为0到10FFFF,可以被划分为字符平面(planes of characters),每个平面包含64K各码点。因此,最底层的平面为基本多语言平面(Basic Multilingual Plane),包括范围从0000到FFFF;下一个平面为增补多语言平面(Supplementary Multilingual Plane),也被称为第一平面(Plane 1),包括范围10000到1FFFF;以及,第二平面(Plane 2),增补表意字符平面(Supplementary Ideographic Plane),包括范围20000到2FFFF;等等。基本多语言平面有时也被称为Plane 0。 
    基本多语言平面(BMP, or Plane 0)包含目前世界上使用的所有书写系统中的全部常用字符,以及一些历史上的不常用字符。 
    增补多语言平面(SMP, or Plane 1)用于一些较少使用的历史上的书写系统,针对特殊目的创建的书写系统,和特殊的标记系统,它们要么无法放入基本多语言平面中,要么特别不常用。 
    增补表意字符平面(SIP, or Plane 2)用于无法放入基本语言平面众所分配区域中/日/韩字符(CJK character)。尽管在SIP中包含少量的常用CJK字符(例如,用于粤语),其中绝大多数字符是仅具有历史意义的不常用字符。 
    增补专用平面(Supplementary Special-purpose Plane, SSP, or Plane 14)用于无法放入基本多语言平面众所分配区域的格式控制字符。 
    3. 一致性 
    符合Unicode一致性要求的实现必须满足本部分定义的标准,以便与其他规范的实现进行交互。 
    3.1 一致性要求 
    3.1.1 未分配的码点(Unassigned Code Points) 
    C4 处理过程不应该把高代理码点(high-surrogate code point)或者低代理码点(low-surrogate code point)解释为抽象字符。 
    C5 处理过程不应该把非字符码点解释为抽象字符。 
    C6 处理过程不应该将未分配的码点解释为抽象字符。 
    3.1.2解释(Interpretation) 
    C7 如果处理过程要解释编码字符的表示,就必须根据标准中确立的字符语义进行解释。 
    C8 不要求处理过程对任何特定的编码字符都作解释。 
      允许处理过程只解释Unicode字符中的一个子集;不需要解释所有Unicode字符。 
      标准中不涉及任何指定字符子集的方法。 
      标准中不涉及自定义区中码点的语义。 
    C9 处理过程不应认为对两个具有规范等价性字符序列(canonical-equivalent character sequence)的解释会不同。 
      该条款包含两层意义:(一)处理过程不应该对两个不同但又具有规范等价性的字符序列由不同的解释;(二)任何处理过程不应假设其他处理过程会对两个不同但具有规范等价性的字符序列进行不同的解释。 
    3.1.3 修改(Modification) 
    C10 如果一个处理过程声称不会修改对一个正确的编码字符表示的解释,则它不能对编码字符的表示进行任何修改,除非是用具有规范等价性的字符序列进行替换,或者是删除非字符的码点。 
      用具有规范等价性的字符序列替换原有字符序列不会修改对文本的解释。 
      替换或者删除处理过程不能会不进行解释的字符序列,不修改对文本的解释。 
      当在不同计算机体系结构间转换字符序列时,对字符序列位或者字节顺序的改变,不修改对文本的解释。 
      将一个正确的编码字符的表示从一种Unicode字符编码格式转换为另一种编码格式时,不修改对文本的解释。 
      将编码单元序列的字节串行化从一种Unicode字符编码方案转换为另一种编码方案时,不修改对文本的解释。 
      如果在处理过程中意外遇到一个没有明确内部用途的非字符,在实现中可以发出错误,或者删除或忽略该非字符。如果没有采取这些选择,这个非字符应该被作为一个为分配的码点。 
    3.1.4 字符编码格式(Character Encoding Forms) 
    C11 当处理过程对一个声称以某种Unicode字符编码格式存在的编码单元序列进行解释时,必须按照相应的码点序列进行解释。 
    C12 当处理过程以某种Unicode字符编码格式生成编码单元序列时,不应生成形式错误(ill-formed)的编码单元序列。 
    C12a 当处理过程对一个声称以某种Unicode字符编码格式存在的编码单元序列进行解释时,应该将形式错误的编码单元序列看作错误条件,而不能将序列解释为字符。 
    3.1.5 字符编码方案(Character Encoding Schemes) 
    C12b 当处理过程对一个具有某种Unicode字符编码方案的字节序列进行处理时,应该根据字节顺序和标准中针对字符编码方案设立的字节顺序标记(byte order mark)使用规范,进行解释。 
    3.1.6 双向文本(Bidirectional Text) 
    C13 用于显示包含从右到左的字符文本的处理过程,当没有高层协议时,必须以对文本应用双向算法后同样的顺序显示所有具有可见表示的字符(不包括格式字符)。 
    3.1.7 正规化形式(Normalization Forms) 
    C14 以某种正规化形式生成Unicode文本的处理过程,必须与Unicode Standard Annex #15 "Unicode Normalization Forms"中定义的规范相符合。 
    C15 测试Unicode文本是否具有某种正规化形式的处理过程,必须与必须与Unicode Standard Annex #15中定义的规范相符合。 
    C16 将文本转换为某种正规化形式的处理过程必须生成Unicode Standard Annex #15中规定的结果。 
    3.1.8 标准的引用(Normative References) 
    C17 对标准、属性别名、属性值别名或者Unicode算法的标准引用,必须依照Unicode标准种指定的格式。 
    C18 高层协议不能对临时属性进行标准引用。 
    3.1.9 Unicode算法(Unicode Algorithms) 
    C19 如果处理过程声称实现某个Unicode算法,则必须符合标准中定义的算法规范,除非被高层协议改变。 
    3.2 术语定义 
    以下是对一致性条款中所使用术语的准确定义。 
    3.2.1 字符的身份和语义(Character Identity and Semantics) 
    D1 标准的行为(normative behavior):Unicode标准中的标准行为包括以下列表,以及在一致性条款种指定的其他行为。 
    1. 字符组合; 
    2. 规范化的分解; 
    3. 兼容的分解; 
    4. 规范的排序行为; 
    5. 双向行为; 
    6. 联合jamo行为(conjoining jamo behavior); 
    7. 变化选择; 
    8. 正规化。 
    D2a 字符身份(character identity):一个字符的身份是由它的字符名称、表示的字形确定的。 
    D2b 字符语义(character semantics):一个字符的语义是由它的身份、标准的属性和行为决定的。 
    3.2.2 字符与编码(Characters and Encoding) 
    D3 抽象字符(abstract character):信息的单元,用于文本数据的组织、控制或表示。 
      抽象字符没有具体的形状,不应与字形混淆。 
      Unicode标准中没有直接编码的抽象字符经常可以使用组合字符序列表示。 
    D4 抽象字符序列:抽象字符的有序序列。 
    D4a Unicode编码空间(Unicode codespace):从0到10FFFF的整数空间(十六进制)。 
    D4b 码点(code point):Unicode编码空间中的任何一个整数值。 
      一个码点也称为一个编码位置。 
    D5 编码字符(encoded character):在一个抽象字符和一个码点间的关联。 
      在Unicode中,为了与其它标准兼容,一个单个的抽象字符可能与多个码点对应。 
      一个单个的抽象字符也可能使用一个码点序列表示。 
    D6 编码字符表示(coded character representation):一个码点序列。通常,是由编码字符的序列组成,但也可能包含非字符或保留的码点。 
      编码字符表示也称为编码字符序列(coded character sequence)。 
      在内部,处理过程可能会在编码字符表示中使用非字符码点。但是,这些非字符码点可能不会被解释成抽象字符;并且,如果这些非字符码点被具有一致性的处理过程删除,不构成对编码字符表示解释的修改。 
    D7a 不赞成使用的字符(deprecated character):强烈不鼓励使用的编码字符。 
      在标准中保留不赞成使用的字符,以便使以前相容的数据仍然与今后的Unicode标准保持一致性。 
    D7b 非字符(noncharacter):被永久保留做内部使用的码点,不应用于交换。非字符包括值U+nFFFE和U+nFFFF(n表示十六进制整数从0到10),以及值从U+FDD0到U+FDEF。 
    D7c 保留的码点(reserved code point):Unicode标准中保留的,用于今后分配的码点。也称为位分配码点(unassigned code point)。 
      代理码点和非字符码点是已分配的码点,但不是分配给字符。 
    D8 高层协议(higher-level protocol):任何超出Unicode标准范围,对Unicode字符进行解释协议。 
    D8a Unicode算法(Unicode Algorithm):对处理过程的逻辑描述,用于获得涉及Unicode字符的指定结果。 
    3.2.3 属性(Properties) 
    (1)标准的和指示性属性(Normative and Informative Properties) 
    Unicode字符属性可以分为标准的和指示性的。 
    D9 标准属性(normative property):Unicode字符属性,它的取值必须为与标准相一致。 
    D9a 指示性属性(Informative property):Unicode字符属性,它的取值仅仅是为了提供更多信息。 
    D9b 临时的属性(provisional property):Unicode字符属性,它的取值未被批准、试验性的,也可能是不完全的。 
    (2)简单的和衍生出的属性(Simple and Derived Properties) 
    D9c 简单属性(simple property):Unicode字符属性,它的取值在UCD,the Unicode Character Database(或标准中的其他地方)直接指定,并且它的取值无法从其他简单属性中衍生出来。 
    D9d 衍生属性(derived property):Unicode字符属性,它的取值可通过算法从一些简单属性的组合中衍生出来。 
    (3)属性别名(Property Aliases) 
    D10 属性别名(property alias):特定Unicode字符属性的一个唯一标示名。 
      用于属性别名的标示名中仅包含ASCII中的字母、数字和下划线。 
      为每个属性别名分别定义了长、短两种形式的名称。短的形式一般只有两个或三个字符长,便于在标记语言中用于标记属性。 
    D10a 属性值别名(property value alias):为Unicode字符属性的特定取值定义的唯一标示名。 
      用于属性值别名的标示名中仅包含ASCII中的字母、数字和下划线,或者是特殊的值"n/a"。 
      为每个属性值别名分别定义了长、短两种形式的名称。 
      属性值别名仅在相关联的特定属性环境中唯一。 
    (4)却省属性值(Default Property Value) 
    D11 却省属性值(default property value):针对一个给定的Unicode属性,用于指派给未分配的码点或没有明确指定其他属性值的属性值。 
    (5)私用(Private Use) 
    D12 私用码点(private-use code point):在范围U+E000到U+F8FF、U+F0000到U+FFFFD和U+100000到U+10FFFD内的码点。 
      私用码点被认为已分配给字符,但标准中没有指定对私用码点相关联的抽象字符的解释。 
      私用码点可能会被赋予却省的属性值,但这些却省值可以被对私用码点进行解释的高层协议替换。 
    3.2.4 组合(Combination) 
    D13 基字符(base character):在书写上,不与前面的字符进行组合的字符,它既不是控制字符也不是格式字符。 
    D14 组合字符(combining character):在书写上,与前面的基字符进行组合的字符。称组合字符应用于基字符。 
      组合字符不单独使用。它们包括重音符、变音符、希伯莱文中的点、阿拉伯文元音符号等。 
      尽管组合字符用来与基字符组合显示的,但可能出现两种情况(1)在组合字符前没有基字符;(2)处理过程无法执行组合操作。在这两种情况下,处理过程可能会不进行书写上的合并而显示组合字符。 
      在编码表中,组合字符的表示使用虚线圆圈描绘。当与前面的基字符组合显示时,基字符要出现在虚线圆圈的位置上。 
      组合字符一般具有它们的基字符的属性,同时保留它们的组合属性。 
      控制字符和格式字符,如tab和right-left mark不是基字符。 
    D15 非间距标记(nonspacing mark):在显示时,位置取决于基字符的组合字符。这些字符一般在可视基线上不占用空间。 
      这些字符可能会很大,影响它们的基字符相对于前后基字符的放置。 
    D16 间距标记(spacing mark):不是非间距标记的组合字符。 
      一般来说,间距标记的行为与基字符没有太大区别。 
    D17 组合字符序列(combining character sequence):一个字符序列,由一个基字符后跟了一个或多个组合字符组成,或者是一个或多个组合字符的组成的序列。 
    D17a 不良的组合字符序列(defective combining character sequence):一个不是以基字符开始的组合字符序列。 
      当组合字符序列出现在串的开始位置,或者跟在控制字符或格式字符后出现时,产生不良的组合字符序列。 
    3.2.5 分解(Decomposition) 
    D18 可分解字符(decomposable character):根据分解映像表,与一个或多个字符组成的序列等价的字符。也被称作预组合字符(precomposed character)或复合字符(composite character)。 
    D19 分解(decomposition):与一个可分解字符等价的一个或多个字符组成的序列。一个字符序列的完全分解,是对序列中每个字符进行分解直到没有字符可以进一步分解。 
    (1)兼容的分解(Compatibility Decomposition) 
    D20 兼容的分解(compatibility decomposition):递归应用Character Names List中的兼容映像表和规范映像表,以及Conjoining Jamo Behavior中的定义,对字符进行分解,直到没有任何字符可以进一步分解,并根据Canonical Ordering Behavior中的定义对非间距标记进行重新排序。 
    D21 兼容的可分解字符(compatibility decomposable character):兼容分解的结果与规范分解结果不相同的字符。 
    (2)规范的分解(Canonical Decomposition) 
    D23 规范的分解(canonical decomposition):递归应用Character Names List中的规范映像表,以及Conjoining Jamo Behavior中的定义,对字符进行分解,直到没有任何字符可以进一步分解,并根据Canonical Ordering Behavior中的定义对非间距标记进行重新排序。 
    D21 规范的可分解字符(compatibility decomposable character):与规范分解结果不相同的字符。 
    D24 规范等价性(canonical equivalent):如果两个字符序列的完全规范分解结果相同,称它们具有规范的等价性。 
    3.2.6 代理(Surrogates) 
    D25 高代理码点(high-surrogate code point):位于范围U+D800到U+DBFF内的Unicode码点。 
    D25a 高代理编码单元(high-surrogate code unit):在范围D800到DBFF内的16位编码单元,作为UTF-16中代理对的起始编码单元。 
    D26 低代理码点(low-surrogate code point):位于范围U+DC00到U+DFFF内的Unicode码点。 
    D26a 低代理编码单元(low-surrogate code unit):在范围DC00到DFFF内的16位编码单元,作为UTF-16中代理对的结尾编码单元。 
    D27 代理对(surrogate pair):由两个16位编码单元组成的序列来表示单个的抽象字符,其中,代理对的第一部分为高代理编码单元,第二部分为低代理编码单元。 
      代理对仅用于UTF-16。 
      孤立的代理编码单元自身没有解释。 
    3.2.7 Unicode编码格式(Unicode Encoding Forms) 
    D28 Unicode标量值(Unicode scalar value):除了高代理和低代理码点外的其他所有Unicode码点。 
    D28a 编码单元(code unit):为了处理和交换,表示编码文本单元的最小的位组合。 
      编码单元是计算机存储中的特定单元。Unicode标准在UTF-8中使用8位编码单元,在UTF-16中使用16位编码单元,在UTF-32中使用32位编码单元。 
      在Unicode标准中,一些编码单元的特定值不能单独用于表示编码字符。该限制条件应用于UTF-16中孤立的代理码点,以及UTF-8中的字节80-FF。 
    D28b 编码单元序列(code unit sequence):一个或多个编码单元的有序序列。 
      当编码单元是8位时,编码单元序列也可被称作字节序列。 
      一个编码单元序列可能只有一个单个的编码单元。 
      在程序设计语言中,字符串类型的值基本由编码单元序列组成。 
      依赖字符编码标准的结构,可能要使用编码单元序列(包含多个编码单元)来表示一个单个的编码字符。 
    D29 Unicode编码格式将每个Unicode标量值分配给一个唯一的编码单元序列。 
      由于历史原因,Unicode编码格式也被称作Unicode(or UCS) transformation formats(UTF)。 
      在Unicode标量值集合与针对Unicode编码格式的编码序列集合间的映射是一对一的。 
      对给定的编码格式,存在编码单元序列没有相关联的Unicode标量值。 
    D29a Unicode串(Unicode string):由Unicode编码格式中编码单元组成的编码单元序列。 
    D29b 8位Unicode串(Unicode 8-bit string):只包含UTF-8编码单元的Unicode串。 
    D29c 16位Unicode串(Unicode 16-bit string):只包含UTF-16编码单元的Unicode串。 
    D29d 32位Unicode串(Unicode 32-bit string):只包含UTF-32编码单元的Unicode串。 
    D30 形式不良的(ill-formed):如果具有Unicode编码格式的Unicode编码单元序列没有遵照Unicode编码格式规范,就称为形式不良的。 
      如果编码单元序列对应的码点位与Unicode标量范围之外,就是形式不良的。 
      UTF-8对起始字节和后续字节的字节范围有严格的约束。违反这些约束,将使生成的编码单元序列无法映射到Unicode标量值上,产生一个形式不良的编码单元序列。 
    D30a 形式良好的(well-formed):遵照Unicode编码格式规范的Unicode编码单元序列,就成为形式良好的。 
    D30b 形式良好的UTF-8编码单元序列(well-formed UTF-8 code unit sequence) 
    D30c 形式良好的UTF-16编码单元序列(well-formed UTF-16 code unit sequence) 
    D30d 形式良好的UTF-32编码单元序列(well-formed UTF-32 code unit sequence) 
    D30e 具有Unicode编码格式(in a Unicode encoding form):如果一个Unicode串是由某个特定的Unicode编码格式的形式良好的编码单元序列组成,称该Unicode字符串具有Unicode编码格式。 
    UTF-32 
    D31 UTF-32编码格式(UTF-32 encoding form):一种Unicode编码格式,为每个Unicode标量值分配一个单一的无符号的32位编码单元,编码单元的数字值与Unicode标量值相同。 
      因为代理码点没有包括在Unicode标量值集合中,所以位与范围0000D800到0000DFFF间的UTF-32编码单元使形式不良的。 
      任何大于0010FFFF的UTF-32编码单元是形式不良的。 
    UTF-16 
    D35 UTF-16编码格式(UTF-16 encoding form):一种Unicode编码格式,为处在范围U_0000到U+D7FF和U+E000到U+FFFF内的每个Unicode标量值分配一个单一 的无符号的16位编码单元,编码单元的数字值与Unicode标量值相同;位处在范围U+10000到U+10FFFF内的每个Unicode标量值分配 一个代理对。 
      因为代理码点不是Unicode标量值,位于范围D800到DFFF间单独的UTF-16编码单元是形式不良的。 
    UTF-16 Bit Distribution 
    Scalar Value UTF-16 
    xxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxx 
    000uuuuuxxxxxxxxxxxxxxxx 110110wwwwxxxxxx110111xxxxxxxxxx 
    wwww=uuuuu-1 
    UTF-8 
    D36 UTF-8编码格式(UTF-8 encoding form):一种Unicode编码格式,位每个Unicode标量值分配一个由一到四个无符号字节组成的序列。 
    UTF-8 Bit Distribution 
    Scalar Value 1st Byte 2nd Byte 3rd Byte 4th Byte 
    00000000 0xxxxxxx 0xxxxxxx 
    00000yyy yyxxxxxx 110yyyyy 10xxxxxx 
    zzzzyyyy yyxxxxxx 1110zzzz 10yyyyyy 10xxxxxx 
    000uuuuu zzzzyyyy yyxxxxxx 11110uuu 10uuzzzz 10yyyyyy 10xxxxxx 
    编码格式转换(Encoding Form Conversion) 
    D37 编码格式转换:在一种Unicode编码格式的编码单元序列与另一种Unicode编码格式的编码单元序列间,直接定义的转换。 
       * 在Unicode标准实现中,一个典型的API在逻辑上,将输入的编码单元序列转化为Unicode标量值(码点),然后将标量值转化为输出的编码单元序列。然而,可以直接在不同编码格式间进行转换,以获取更高的效率。 
       * 具有一致性的编码格式转换过程应将任何形式不良的编码单元序列作为一个错误条件。 
    3.2.8 Unicode编码方案(Unicode Encoding Schemes) 
    D38 Unicode编码方案:针对Unicode编码格式的一种指定的字节串行换,也可包括处理字节顺序标记(byte order mark, BOM)的规范。 
    D39 UTF-8编码方案(UTF-8 encoding scheme):对UTF-8编码单元序列进行串行化的Unicode编码方案,字节序列与编码单元序列本身完全一致。 
    D40 UTF-16BE编码方案(UTF-16BE encoding scheme):将UTF-16编码单元序列串行化为big-endian格式字节序列的Unicode编码方案。 
    D41 UTF-16LE编码方案(UTF-16LE encoding scheme):将UTF-16编码单元序列串行化为little-endian格式字节序列的Unicode编码方案。 
    D42 UTF-16编码方案(UTF-16 encoding scheme):将UTF-16编码单元序列串行化为big-endian或者little-endian格式字节序列的Unicode编码方案。 
      在UTF-16编码方案中,与U+FEFF对应的初始字节序列,被解释为字节顺序标记(BOM),用于区分两种字节顺序。初始字节顺序表明是big-endian顺序,表明是little-endian顺序。BOM不是文本内容的一部分。 
      UTF-16编码方案可能以BOM开始,也可能没有。然而,如果没有BOM,也没有高层协议指示,UTF-16编码方案的字节顺序为big-endian。 
    D43 UTF-32BE编码方案(UTF-32BE encoding scheme):将UTF-32编码单元序列串行化为big-endian格式字节序列的Unicode编码方案。 
    D44 UTF-32LE编码方案(UTF-16LE encoding scheme):将UTF-32编码单元序列串行化为little-endian格式字节序列的Unicode编码方案。 
    D45 UTF-32编码方案(UTF-32 encoding scheme):将UTF-32编码单元序列串行化为big-endian或者little-endian格式字节序列的Unicode编码方案。 
      在UTF-32编码方案中,与U+FEFF对应的初始字节序列,被解释为字节顺序标记(BOM),用于区分两种字节顺序。初始字节顺序<00 00 FE FF>表明是big-endian顺序,表明是little-endian顺序。BOM不是文本内容的一部分。 
      UTF-32编码方案可能以BOM开始,也可能没有。然而,如果没有BOM,也没有高层协议指示,UTF-16编码方案的字节顺序为big-endian。 
    3.2.9规范排序行为(Canonical Ordering Behavior) 
    用于对组合字符序列提供无歧义的解释,以便能按照可预知的方式创建和交换包含组合字符的序列。正规化是规范排序行为的另一个重要应用。 
    在Unicode标准中,组合字符序列中字符的顺序按照以下原则解释: 
      所有组合字符必须跟在所应用的基字符后面。 
      封闭的标记(enclosing mark)将包围基字符以及标记之前的所有组合字符。也包围它之前的其他封闭标记。 
      double diacritic的结合程度比其他非间距标记(nonspacing mark)要松。当显示时,double diacritic的位置在其他变音符之上,不包括封闭的变音符。 
      具有相同组合类别(combining class)的组合标记在书写上的位置一般是由所修饰的基字符向外排列。一些特定的非间距标记将改变却省的排列行为,与相邻的非间距标记并行排列。当并行排列时,编码的顺序与书写中占支配的顺序有关。 
      如果组合字符的组合类别不同,将不会有显示形式或语义上的差别。 
    (1)组合类别(Combining Class) 
    D46 组合类别:分配给每个Unicode组合字符的数字值,用于确定与那些组合字符在排字上相互作用。 
      如果组合字符间在排字上相互作用,则具有相同的组合类别;否则,具有不同类别。 
      封闭字符和间距组合字符的组合类别与它们的基字符相同。 
      组合类别具有的特定数字没有特别的重要性,只是用来比较是否相等,区分不同的组合类别。 
    (2)规范排序(Canonical Ordering) 
    对一个被分解的字符序列的规范排序,是根据组合类别对每个组合字符序列进行排序来完成的。字符序列的规范排序不反映任何语言正确性或偏好。 
    对被分解的字符序列D进行规范排序的算法为: 
    R1 对D中的任意字符x,定义p(x)为字符x的组合类别。 
    R2 如果在D中存在想的字符对(A,B),并且p(B)不为零,p(A)>p(B),则交换两个字符。 
    R3 重复执行R2,直到在D中没有发生任何交换。 
    (3)Conjoining Jamo Behavior 
    在Unicode标准中包含了一套预组合的Hangual音节,以及一套用于表示古老的韩文音节和现代韩文音节的jamo。 
    4. 实现指南 
    4.1 编码转换(Transcoding to Other Standards) 
    一般,在Unicode标准和其他编码标准间的映射需要通过表(table)来完成,而不是算法转换。使用表查找常常具有比简单算法转换更高的效率。 
    (1)多级表(Multistage Tables) 
    转 换表需要空间。即使是很小的字符集也经常会映射到Unicode标准中几个不同的区块中,因此,至少在一个转换方向上(从Unicode标准到其他编码标 准或相反),可能会包含多至64K个项(针对BMP)或1,088K个项(针对全部编码空间)。有多个方法用于减少映射表的内存空间需求,这些方法不仅可 用于转换表,也可用于其他实现Unicode标准的表结构,包括字符属性数据、case映射等等。 
    (2)Flat Tables 
    如果磁盘空间不是问题,虚拟内存体系可以为flat table安排可接受大小的工作集,因为各字符的使用频率有很大不同,即使是小字符集也包含一些不常使用的字符。并且,需要转换为给定字符集的数据中的字符一般不会来自Unicode标准中的所有区块。 
    (3)Ranges 
    提 供一个精心创建的嵌套范围判断对表进行优化,可能比较吸引人。但由于分支损失,这种方法会对现代的高度流水线式的处理器体系造成不必要的性能耗费。一种快 速的解决方案是采用优化的两级表,可以在编码中不包含任何测试或分支指令。尽管哈希表的速度不如多级表,但也可用于空间优化。 
    (4)两级表(Two-Stage Tables) 
    两 级表示常用的一种减少表的大小的机制。两级表使用一个指针和却省值的数组。如果指针为空NULL,查找返回却省值。否则,指针指向用于第二级查找的数值 块。对于BMP字符,按照高字节和低字节值来组织这样的两级表非常有效,第一级是由256个指针组成数组,每个第二集区块中包含256个值。对于增补字 符,应采取不同的方法构造指针和二级数组,以便充分考虑增补字符在剩余编码空间中稀疏的散布。 
    (5)优化的两级表(Optimized Two-Stage Table) 
    当 任何区块相同时,对应的指针只需其中一个区块。对编码转换表而言,这种情况一般出现在当区块中的字符仅仅映射到"却省"或"无法匹配"的字符时。不是使用 空指针NULL和一个却省值,而是创建了一个却省项的"共享"块。由于避免使用测试和分支,这种策略可以提供接近于简单数租访问的速度,却大大节省了存储 空间。 
    (6)多级表调节(Multistage Table Tuning) 
    给定一个具有任意大小和内容的表,可以较容易的创建一个小的应用程序,来计算多级表的最佳级数和它们的宽度。通过调节级数和它们的索引指针数组的宽度,可以在表大小和平均访问时间之间进行折衷。 
    4.2 ANSI/ISO C wchar_t 
    在ANSI/ISO C中,为固定宽度的宽字符定义了类型wchar_t,ANSI/ISO C将宽字符集语义的定义留给了特定的实现。 
    wchar_t的宽度是由编译器指明的,可以只有8位大小。因此,需要在不同C或C++编译器间可移植的程序不应该使用wchar_t存储Unicode文本。 
    对 于UTF-16的实现,可以使用宏macro或者类型定义typedef(如UNICHAR),编译为unsigned short或者wchar_t(依赖于目标编译器和平台)。对UTF-32的实现可以使用编译为unsigned int或wchar_t的宏或者是类型定义。这样的选择使在不同的系统平台和编译其中可以正确编译。 
    4.3 未知和缺少的字符(Unknown and Missing Characters) 
    4.3.1 保留的和私用的字符编码(Reserved and Private-Use Character Codes) 
    有两类码点,即使是完全的Unicode标准实现也无法正确解释: 
      被保留的码点; 
      在私用区中的码点。 
    一个实现不应试图去解释这样的码点。然而,在实际中,应用程序必须处理为分配的码点或私用字符。例如,当应用程序所处理的文本是由一个实现更新版本的Unicode标准的系统创建的,其中包含更多的分配字符。 
    对未知字符显示的选择包括将码点显示为四到六位十六进制数字,显示一个黑得或白的方块,针对保留字符和私用字符分别显示适合的字形,或者什么都不显示。一个实现不能删除这样的字符,也不能无目的地转换为其他字符。 
    4.3.2可解释但无法显示的字符(Interpretable but Unrenderable Character) 
    一个实现可能接收一个分配给Unicode字符的码点,但无法显示它,因为没有字体或者无法正确显示。 
    在这种情况下,实现可能会对用户的询问提供进一步有限的反馈,如对数据进行适当的排序,显示它的书写系统,或者以却省放时显示码点。对无法显示的(但是已分配的)码点和未分配的码点,实现可以通过为无法显示的码点使用指示类别的不同字形表示。 
    4.3.3却省的属性值(Default Property Value) 
    要使实现可以正常工作,需要把未分配的码点看作字符分配却省的属性值,因为各种算法都需要分配给每个码点的属性值来运作。这些却省值不是对所有未分配的码点都相同,因为码点中的某些范围需要不同的属性值以便与将来期望的分配做到最大兼容。 
    除非被特指,却省属性值不是标准的,具有一致性的实现可以使用其他值。例如,取代却省值,实现可能使用以下规则,为一块未分配字符插入相邻已分配字符的属性值。 
      注意在两个方向上最接近的已分配字符,如果它们处在相同的块中具有相同的属性值,则使用这些值。 
      从任一区块的边界开始,一直扩展到块内最近的已分配字符处为止,使用区块中字符对应的属性值。 
      如果所有的码点完全位于空的或未分配的块中,使用对应属性的却省值。 
    4.3.4却省的可忽略的码点(Default Ignorable Code Points) 
    一 般,在可支持字符集外的码点使用一个应变的字形显示,如一个黑方块。然而,格式和控制字符不应该由可见的字形(尽管它们对其他字符的显示有影响)。除非对 于一些特定的处理,这些字符也被忽略,例如,字符ZERO WIDTH NON-JOINER在对照(collation)中忽略。为在不同版本的标准间保证最大程度的兼容性,范围U+2060到U+206F,U+FFF0到 U+FFFB,和U+E0000到U+E0FFF保留给格式和控制字符。在这些范围中的位分配码点应该在处理和显示中被忽略。 
    4.4 处理UTF-16中的代理对(Handling Surrogate Pairs in UTF-16) 
    在形式良好的UTF-16中,在一个低代理码点之前只能是一个高代理码点,而不能是另一个低代理码点、一个非代理码点或者是文本的开头。一个高代理码点的后面也只能跟一个低代理码点,而不能是另一个高代理码点、一个非代理码点或者是文本的结尾。 
    高代理码点和低代理码点被分配了不相交的编码单元,非代理的码点也不会使用这些范围内的编码单元值表示。因此,在形式良好的UTF-16中的每个编码单元必须只满足下面三个可能的条件之一: 
      一个单一的非代理编码单元表示的码点范围是0到D7FF或E000到FFFF; 
      一个高代理码点表示代理对的第一部分; 
      一个低代理码点表示代理对的第二部分。 
    最多访问两个编码单元,使用UTF-16编码格式的处理过程就可以解释任何Unicode字符。确定字符边界最多只需要扫描前一个或后一个编码单元,而不需考虑其他部分。 
    只要实现不去除代理对中的任一编码单元,或者在代理对中两个编码单元间错误的插入另一个字符,就可以保证数据的完整性。而且,即便数据被破坏了,错误也是局部的。 
    UTF-16具有非常有利的频率分布,在所有文本数据中的大多数部分中,代理对非常罕见,非代理码点将非常普遍。这不仅有利于减少由于处理变长编码而带来的性能损失,也允许一些处理过程可以不对代理对采取特别的操作,或者使用已有处理字符序列的机制来处理代理对。 
    实现必须在处理UTF-16文本时完全支持代理对。但是,实现中的单独的组件可以具有对代理对不同程度的支持,只要这些组件之间可以正确的组合和交流。对代理对不同程度的支持由两个主要方面决定: 
      实现是否解释增补的字符? 
      实现是否保证代理对的完整性? 
    Surrogate Support Levels 
    Support Level Interpretation Interity of Pairs 
    None No supplementary characters Does not guarantee 
    Transparent No supplementary characters Guarantees 
    Weak Some supplementary characters Does not guarantee 
    Strong Some supplementary characters Guarantees 
    不支持代理对,实现就不会对任何增补字符进行解释,也不保证代理对的完整性。 
    透 明的代理对支持(transparent surrogate support),用于这样的组件,如编码格式转换,它可能完全保证对代理对的正确处理,但不解释任何增补字符。也适用于低层串处理操作的组件,一个 Unicode串只是简单地作为编码单元的数组而不顾它们的代理状态,不对串进行解释。 
    不充分的代理支持(weak surrogate support)只正确地处理那些对应可解释字符的代理对,可能调用的组件被保证不会传递无法解释的字符。 
    支持代理对的策略(Strategies for Surrogate Pair Support) 
        处理Unicode标准中高级特性的一些实现可以很容易地被改进,来支持UTF-16的代理对。例如: 
      在文本对照(text collation)中可以把代理对作为"组合字符"来处理。 
      文本的输入可以使用一次按键产生两个Unicode码点的键盘来完成,就如一次ENTRE键可以生成CRLF或者在阿拉伯键盘上的"lam-alef"可以生成两个字符lam和alef的序列。 
      文本截断(truncation)可以使用与保证组合标记紧跟基字符相同的机制。 
    如 果文本编辑器可以保证插入点(insertion point)位于字符边界,就可以阻止用户破坏文本。只要使用文本元素边界,低层的串处理程序(如wcschr)就不用进行修改。实际上,只有某些高层的 处理需要注意代理对;底层的例程可以继续使用对16位编码单元操作,而不需特别对待代理对。 
    4.5 处理数字(Handling Number) 
    在Unicode 中,有一些字符集合用于表示不同书写系统中的十进制数字。在数字上,解释这些字符的系统必须提供正确的数字值。比如,在数字上,对序列解释,具有值20。 
    当从二进制的数字值转换为可视的形式时,可以从不同的书写系统中选择数字。 
    ASCII数字的全角变形(fullwidth)仅是通常数字的兼容变形,应作为一般的西文数字对待。 
    罗马数字和东亚的表意字符数字也是十进制的数字书写体系,但它们在形式上不是以10为基数的数字系统。因此,不可能采用一对一的方式转换成像123456.789的形式。 
    使用表意字符,也可能以两种方法书写数字。如数字1,234可以表示为"一千二百三十四"或"一二三四"。在数字解析使支持这些数字意味着实现必须能区分这两种情况。 
    有时候数字需要解析,但它们并不是数的一部分。例如由字母和数字组成的标示符。 
    只有在另一层上(如实现一个完整的数学公式解析器),对上标(superscripting)的解释才是至关重要的。 
    4.6 正规化(Normalization) 
    (1)可选择的拼写(Alternative Spelling) 
    在Unicode标准中对最常用的一些加重音符的字符分配明确的编码。这些字符也可以通过组合获得,对于加重音符的字母,可以由基字符和非间距标记(nonspacing mark)组合而来。 
    Unicode标准提供对可由基字符加一个或多个非间距标记组合而来字符的分解。分解映射与特定Unicode标准的版本有关。 
    (2)正规化(Normalization) 
    系统可能会将Unicode编码格式的文本正规化为特定的序列,如将组合字符序列正规化为由预组合字符的序列,或者相反。 
    无法处理非间距标记的系统,可以正规化为预组合字符,适用于大多数基于拉丁语的现代语言。对于无法处理的组合字符,系统可以使用替代显示方法,至少在显示上表示组合。 
    对可以处理非间距标记的系统,执行正规化消除预组合字符可能会有用,使系统对组合字符有统一的表示,保持对这类字符处理的一致性。 
    4.7 压缩(Compression) 
        使用Unicode字符编码可能会增加用于保存文件文本部分的存储和内存空间。因此,对Unicode文件或串进行压缩是一个很好的选择。压缩往往建立一个更高层的协议,并且依赖于所使用的压缩方法的知识进行交换。 
    4.8 换行的原则(Newline Guidelines) 
    换 行符在不同的平台上表示为:carriage return(CR)、line feed(LF)、CRLF,或next line(NEL)。不仅换行符使用不同的字符表示,并且在相同平台上,它们也具有不明确的行为。当转换字符集编码时,这些字符通常被直接转换为对应的 Unicode码点。这意味着,即使是处理纯Unicode文本的程序也必须解决这些问题。特别是随着Web的出现,在一台机子上的文本可能具有不同的来 源,将引起很大问题。 
    换行符用来明确指示行的边界。 
    4.8.1 定义(Definitions) 
    Hex Values for Acronyms 
    Acronym Name Unicode ASCII 
    CR carriage return 000D 0D 
    LF line feed 000A 0A 
    CRLF carriage return and line feed 000D,000A 0D,0A 
    NEL next line 0085 85 
    VT vertical tab 000B 0B 
    FF form feed 000C 0C 
    LS line separator 2028 n/a 
    PS paragraph separator 2029 n/a 
    在Unicode标准中,没有正式地分配控制字符,而是为各种7位和8位字符编码标准中使用控制字符提供相应的码点。确保了Unicode标准与其他编码标准的相关性和相互映射。 
    缩写NLF(newline function)表示针对一个新行分隔符的一般控制功能。 
    4.8.2 背景(Background) 
    段落分隔符(paragraph separator)用于指示段落之间的分隔。行分隔符(line separator)指示在何处进行断行,特别是在一个段落中。 
    记录分隔符(record separator)用于分隔记录。例如,当交换表格式数据时,一种普通的格式是使用TAB分隔单元和在一行单元后使用CRLF。尽管这种功能与行分隔不是正好相同,但使用了同样的字符。 
    NLF开始时作为行分隔符。现在,在一些简单的文本编辑器中还作为行的分隔符。随着平台和程序开始使用自动分行进行字处理,这些字符被用于表示段落分隔符。 
    一旦NLF被用来表示段落分隔符,在一些情况下,另一个控制字符就被作为行分隔符使用。例如,在Microsoft Word中,就使用vertical tabulation(VT)。 
    4.8.3 建议(Recommendation) 
    在Unicode 中,定义了两个明确的分隔字符:U+2029 PARAGRAPH SEPARATOR(PS)和U+2028 LINE SEPARATOR(LS)。在Unicode文本中,应该在所表达功能明确的地方使用PS和LS字符。否则,当从其他字符集转换为Unicode时,当 解释文本中的字符时,和当从Unicode转换为其他字符集时,使用以下规则处理NLF。 
    即使实现知道在一个特定的平台上用哪个字符表示NLF,在输入和解释时CR、LF、CRLF和NEL应该被相同对待。只要在输出时,才有必要进行区分。 
    (1)从其他字符编码集转换 
    R1 如果知道NLF的确切的用法,则转换为LS或PS。 
    R1a 如果不知道NLF的确切用法,则映射为与平台对应的NFL。 
    (2)解释文本中的字符 
    R2 总把PS解释为段落间隔,把LS解释为行间隔。 
    R2a 在字处理中,把任一NLF都解释为PS。 
    R2b 在简单文本编辑中,把任一NLF都解释为LS。 
    R2c 在解析中选择最安全的解释。 
    例如,对R2c,涉及断句启发规则的实现会按照以下方法,将NLF安全的解释为LS: 
      当一个NLF应是PS时,假设把它解释为LS。因为多数段落总是以标点符号结束,这只会在个别情况造成对句子边界的错误识别。 
      当一个NLF应是LS时,假设把它解释为PS。在这种情况下,行分隔符将是句子断开,对断句启发规则带来很大错误。 
    (3)转换为其他字符编码集 
    R3 如果已知转换的目标,根据目标协定,适当地对NLF、LS和PS进行映射。 
    例如,当映射为Microsoft Word对文档的内部协定时,LS将映射为VT,PS和其他NLF将映射为CRLF。 
    R3a 如果不知道转换的目标,将NLF、LS和PS映射到平台的换行协定。 
    (4)输入和输出 
    R4 函数readline应该在遇到NLF、LS、FF或PS时停止。在典型的实现中,不包括停止位置的NLF、LS、FF或PS。 
    因为分隔符会丢失,对这种readline函数的使用仅限于与分隔符的类型无关的文本处理。 
    R4a 函数writeline应该根据(3)中的协议转换NLF、LS和PS。 
    (5)页面分隔符 
    FF一般用作页面分隔符,在文本中应该按照情况解释。当在屏幕上显示时,在分隔符后的文本会被强制放如下一页。它与段落分隔符无关:一个段落可以在一页开始在下一页中继续。除非是在页面中显示,在大多数解析过程和readline中,与LS的解释相同。 
    4.9 正则表达式(Regular Expressions) 
    面向字节的正则表达式工具需要扩展以正确处理Unicode。下面是扩展所涉及方面: 
      Unicode是一个很大的字符集,只适用于处理小字符集的正则表达式工具可能无法调整。 
      Unicode包括多种语言,它们具有与英语或其他西欧语言非常不同特性。 
    4.10 纯文本中的语言信息(Language Information in Plain Text) 
    4.10.1 语言标记的需要 
    在纯文本数据中嵌入语言信息的需要经常被夸大。一些普通操作,如对照(collation)很少需要这些额外信息。 
    然 而,语言信息对某些操作非常有用,如对一个混合语言的文档执行拼写检查或者连字(hyphenating)。对于为无格式文本选择却省字体也非常有用,例 如日文字体中的省略符号具有与英文字体不同的外观。当前的字体和布局(layout)技术基于语言信息产生不同结果。尽管语言信息对于执行文本-语音转换 (text-to-speech)操作有用,但当前的文本-语音转换软件都必须对文本执行非常复杂的语法分析,因此确定语言的额外工作就不那么重要了。 
    语言信息可以使用带外信息(out-of-band)或内嵌标记(inline tag)表示。在内部实现中,通常使用带外信息,保存在与文本并联的数据结构中,而不是嵌入到文本数据中。带外信息不影响对文本的正常处理,还可以轻松的支持对文本的操作。 
    4.10.2 语言标记与汉字统一 
    对Unicode中汉字统一的一个常见误解是觉得没有语言信息就无法正确显示汉字字符。其实,汉字统一的目标和方法是确保文本可读。尽管需要添加字体、大小、宽度和其他格式规格,以便在源和目标机器上准确产生相同的外观,但在没有这些规格时,纯文本也能保证可读。 
    因为不同国家所使用的统一的汉字间的不同,都仅限于格式上的变化,不会引起Unicode中的混乱。在Unicode中的汉字统一不会使读者音唯一不同的字体显示而无法识别一个字符。如果准确的字体信息很重要,最好使用格式文本。 
    4.11 编辑和选择(Editing and Selection) 
    一致的文本元素(Consistent Text Elements) 
    从 用户的角度,文本的基本表示不是所关心的,但重要的是,编辑接口必须对用户所认为的字符提供一个统一的实现。用户希望在鼠标选择、方向键移动、退格等操作 中,这些字符表现得像一个个单元。例如,当实现这些行为后,对一个表示为基字符加非间距组合标记序列的加重音符字母,使用右移方向键时,逻辑上会从基字符 的开始跳到最后一个非间距字符后面。 
    在词中的编辑和选择,一般有三种类型的边界(boundary)。 
    簇边界(cluster boundary) 
    任意定义的簇边界可能会出现在像梵文(Devanagari)这样的书写系统中,选择操作可能会应用于音节或者音节的一部分。在这种情况下,组合字符序列,如ka+vowel sign或者联合的簇ka+halant+ta,作为单一的单元选择。 
    堆叠字符边界(stacked boundary) 
    堆叠字符边界一般比簇边界更细。独立的元素(如梵文vowel sign a)可以不受约束的选择,但是任何堆叠在一起的字符(包括垂直连字符,如阿拉伯文中的lam+meem)只能作为单一的单元选择。 
    原子字符边界(atomic character boundary) 
    原 子字符边界的使用最接近于单个Unicode字符的选择。然而,大多数当前系统都采用某种矩形加亮的方式表示选择操作。这种方法限制了编辑操作的一致性, 因为一些字符序列不是从行的起始处成直线地发展。当字符堆叠时,两种机制被用于对部分选择地显示:直线的和非直线的边界。 
    直线的边界(linear boundary) 
    使用直线边界,将合成字形的全部宽度都归属于序列的第一个字符,认为其余字符没有宽度。 
    这是最简单的一种机制。它的优点是只需要很少的额外实现工作。它的缺点是选择窄字符变得非常困难,更不用说零宽度的字符。需要用户刚好从非间距标记右边开始选择,并且正好拖到左边。如果有多个非间距标记,它也不允许对单个标记进行选择。 
    非直线的边界(nonlinear boundary) 
    使用非直线边界把任何堆叠字符分成各个部分。可以通过对多个矩形加亮,或者对单个字符着色的方法进行表示。 
    注意到,通过更多的操作,一个预组合的字符在删除操作中可以表现得像一个具有原子字符边界组合字符序列一样。这个过程包括动态地获得字符的分解表示,得到用作模拟的组件。 
    在多数系统中,字符时文本中最小的可寻址单元,所以选择操作和属性分配操作(如字体、颜色、字符间距等)都在字符的基础上执行。对于预组合地字符无法模拟这种可寻址性,系统地修改所有文本编辑工具来对字符的一部分进行寻址,会十分低效。 
    由 于文本元素不具有一个单一的概念,因此,对字符边界的编辑也没有一个统一的概念。在不同情况下,用户可能会在编辑过程中使用不同程度的粒度大小。可以考虑 两种方法:首先,用户可能设定对字符边界的一个全局偏好;第二,用户可能有可选的命令机制,如Shift-Delete,可以提供对却省模式更细(或更 粗)的控制。 
    4.12 处理非间距标记的策略 
    依据一下策略,开发者可以实现对非字符间距有效和高效使用的系统和例程。开发者也可以选择适用于绝大多数已有系统的最小限度的技术,和适用于要求更苛刻的情况的复杂技术,如高端的桌面出版。 
    在 这里,术语非间距标记(nonspacing mark)和组合字符(combining character)可以互换使用。有时会使用术语diacritic、accent、stress mark、Hebrew point、Arabic vowel等,而不是非间距标记(它们表示特定类型的非间距标记)。 
    为支持非间距标记,只需要相对较小数量的实现特性。存在多种可能层次的实现。一个最小的系统可以产生较好的结果,并且相对容易实现。要求大多数特性地系统,只是对已有软件地简单修改。 
    因为有一些语言要求非间距标记,如Arabic、Hebrew和印度次大陆的语言,已有一些可以处理这些字符的系统,可以利用已有经验来生成处理Unicode标准中这些字符的多用途软件。 
    显示(rendering) 
    一 部分确定的组合字符序列可以通过简单的替换来有效显示。当遇到一个有基字符加一个或多个非间距组合标记组成的序列时,可以使用表示组合形式的字形进行替 换。在简单地字符显示中,一个非间距组合标记不增加宽度,一个组合字符序列的具有与基字符相同的宽度。当截断串时,从结尾处开始向后执行截断总是最容易。 后续的非间距标记将不会与前面的基字符分开。 
    一个更复杂得显示系统会考虑使用非间距标记时对宽度和字距更细微的调整,或者组合字符序列具有与基字符不同宽度。对大多数应用而言,这样地显示系统并不是必需的。 
    其他处理:正确的多语言比较例程也必须能够把字符序列作为一个字符比较,或者把一个字符看作是一个字符序列。只要提供了适当的数据,这些例程也能处理组合字符序列。当查询串时,要检查目标串中可能会影响最后一个匹配字符解释的附加非间距标记。 
    断行算法一般使用状态机,确定词间的中断。这样的算法可以很容易地改进,来阻止将非间距标记从基字符分开。 
    键盘输入(Keyboard Input) 
    用 于组合字符序列输入的一个常见实现,是使用所谓的dead key。这些键与打字机生成这样序列所使用的机制匹配,通过在非间距标记之后键入基字符。在计算机的实现中,当按下针对重音符的dead key时键盘进入一种特殊的状态,只有当键入一些有限数目的"合法"基字符之一时产生一个预组合的字符。根据需要,可以改进系统来生成组合字符序列或者预 组合的字符。尽管打字员,特别是使用Latin书写系统的,是针对这类系统培训的,然而在Unicode标准中一些书写系统(包括Latin)可能会依据 书写的顺序来实现,用户首先键入基字符,其后跟着重音符或其他非间距标记。 
    在书写顺序的情况下,每一次键入都在屏幕上产生一个不同的自然变化。要给已有的字符添加重音符,用户需要把插入点移到字符后在键入重音符。 
    截断(Truncation) 
    有两种类型的阶段:根据字符数目截断和根据显示宽度截断。根据字符数目截断可能带来数据损失,也可以是无损失的。 
    根据字符数目进行截断使用在,由于存储限制,只有有限数目的字符可以放入某区域;也用于,为了传送和其他目的将文本插入缓冲区中。在后一种情况下,如果在处理前缓冲区中的数据可以无缝的重新组合,或者预先检查一下可能出现的跨缓冲区组合字符序列,就可以做到不丢失数据。 
    当调整数据以适应有现长度的区域时,一些信息将会丢失。在文本边界上进行截断(例如,在组合字符序列的最后或者在最后一个词边界)通常比在最后一个码点后截断更可取。 
    根据显示宽度截取用于有限范围内的可视显示。在这种情况下,截断是依据结果串的宽度而不是字符的数目。在简单的系统中,依据宽度截断很容易,从末尾处开始向后操作减去字符的宽度。由于后续非间距标记对串的尺寸没有贡献,最后结果不会把非间距标记与它们的基字符分开。 
    如果文本环境会更复杂,字符的宽度可能会依赖上下文环境,由于字符间距调整、连字或上下文信息等的作用。对这种系统,一个组合字符的宽度可能会与一个单独的窄字符(如i)的宽度不同。处理这种情况,必须对截断结果进行核查。 
    一个不同的选择是在图形上对字符进行修剪。但不幸的是,结果可能很难看。并且,如果修剪出现在字符之间,可能不会给出任何世界反馈表示字符被删除了。 
    4.13 非间距标记的显示(Rendering Nonspacing Marks) 
    在这里假定使用均衡字体(proportional font),单个字符的宽度可以变化。对于等宽字体(monospaced font),可以使用各种技术,但一般而言,对于这种字体的多数书写系统,可能只有一种正确的显示外观。 
    当 显示的序列中包含多于一个的非间距标记时,却省情况下,非间距标记从基字符向外堆叠。即,如果亮格非间距标记出现在基字符的之上,则第一个非间距标记位于 基字符上面,第二个非间距标记为与第一个标记上面。如果亮格非间距标记出现在基字符的之下,则第一个非间距标记位于基字符下面,第二个非间距标记为与第一 个标记下面。 
    这种却省行为可能会根据排字上的偏好,或者某个特定书写系统中对多个非间距标记的特定正字法处理,而改变。 
    后退的显示(fallback rendering) 
    有几个方法可用于处理在一个固定的可显示集合外未知的组合字符序列。 
    一种方法是Show Hidden,通过先显示基字符再把非间距标记作为单个单元显示,来表示无法描绘序列。 
    另一种方法是Simple Overlap,将重叠的零宽度非间距标记放置在却省的固定位置处,一般所放置的位置例可能的基字符较远。尽管显示结果对于一些字母而言没有吸引力,但在只有一个非间距标记的情况下,结果一般还是可以辨认的。 
    在一个退化的情况下,一个非间距标记作为文本的首字符出现,或者被行分隔符、段落分隔符或其他引起位置分隔的格式符从它的基字符分开。这种结果称为不良的组合字符序列。不良的组合字符序列在显示时,看作是以一个空格作为基字符。 
    双向定位(bidirectional positioning) 
    在双向文本中,非间距标记与它们的基字符一起重新排序。即视觉上,在使用双向算法之后它们应用于相同的基字符。 
    调整(justification) 
    典型地,对文本的完全调整要给间距字符(space character)添加额外的空间;然而,如果只有很少(或没有)间距字符,一些系统会在字符间添加额外的字间隔空(letterspacing)。如果在文本中包含零宽度的非间距标记,则需要对该过程进行改进。 
    因为非间距标记总是跟随它们的基字符,正确的调整过程应该只有当第二个字符是一个基字符时才会在字符见添加字间隔空。 
    规范等价性(Canonical Equivalence) 
    在 显示多个重音符时,必须考虑规范等价性,以便使任两个规范等价的序列显示结果相同。这一点在当规范顺序与习惯的键盘输入顺序不相同时特别重要,如具有元音 符号的阿拉伯文和使用点的希伯莱文。在这些情况下,显示系统得到的是典型的键入顺序或者是经过正规化(normalization)的规范顺序。 
    显示系统应该处理组合标记的任何具有规范等价性的序列。这不会有性能问题,因为对组合标记重新排序所需的时间与其他显示工作的耗时相比微不足道。 
    一个显示系统,在需要时,可以在内部对标记重新排序,只要结果序列是规范等价的。 
    定位方法(Positioning Methods) 
    有一些方法可用于定位非间距标记,使它们相对于基字符和前一个非间距标记(如果有的话)的位置正确。 
    使用连字(positioning with Ligature) 
    一 个固定范围的组合字符序列可以使用相对简单的替换来有效显示。当字形可以表示一个序列<基字符,非间距标记>时,使用这个字形替换组合形式。 因为非间距标记的扩展宽度为零,组合字符序列将自动具有与基字符相同的宽度。跟复杂的文本显示系统可能会采取进一步的措施来处理一些特殊情况,如组合字符 序列的紧排(kern)或者宽度与基字符不同。 
    使用连字可能是支持非间距标记最简单的方法。对于较小的固定字集,如那些对应ISO/IEC 8859-1(Latin-1)重预组合字符的,可以直接采用该方法。因为组合字符序列几乎总是具有与基字符相同的宽度,对这些字符的显示、测量和编辑与 一般连字的情况相比都更容易。 
    如果组合字符序列不能形成一个连字,就需要采用以下两种方法之一。如果这些方法都不可用,则使用后退的方法。 
    根据上下文结构定位(positioning with contextual forms) 
    处理非间距标记定位的一个较通用的方法是使用上下文的结构。在这种情况下,有几个不同的字形对应于重音符的不同位置。依据大致的形状和宽度,基字形(基字符的字形?)通常分成数目较小的一些类别。根据基字形的类别,为非间距标记选择一个特定的字形。 
    在一般情况下,可以从一些具有不同高度的字形中进行选择,以便堆叠字形。这种方法可以与使用连字的方法结合使用,就可在特定情况下,使用连字生成更高的变形。 
    使用增强的字距调整(positioning with enhanced kerning) 
    第三种用于定位读音符号的技术是对常规的字距调整(水平的和垂直的)的扩充。典型地,字距调整过程唯一对字形映射一个位置偏移量。例如,在词语"To"中,"o"应该向"T"下面靠一点。这种系统的扩充则分别映射一个垂直的和水平的偏移量。 
    为了针对一般情况可以有效应用,字距调整过程也必须能够处理比简单字符对更复杂的情况,如在一个基字符后可能有多个读音符号。 
    使用增强的字句调整技术进行定位,也可以和使用连字的方法结合运用。 
    4.14 定位文本元素边界(Locating Text Element Boundaries) 
    Unicode 编码的文本串经常需要被分解为文本元素。文本元素的一般例子包括字符、词、行和句子。文本元素的准确确定可能会依据地区而变化。但要与用户的理解相匹配并 不是总能达到的,因为文本本身并不总是包含足够的信息用于明确决定边界。例如,句点"."(U+002E FULL STOP)的使用具有歧义,有使用于表示句子结束,有时用于缩写,有时则用于数字。然而,在多数情况下,文本边界可以符合用户的理解。 
    4.15 标识符(Identifiers) 
    Unicode 标准的实现面临的一个常见任务是提供针对标识符的解析工具。为了促进在基于Unicode字符的解析器中对标识符的标准化处理,这里针对标识符语法的定义 提出一套指导方针。这些指导方针并不比普通程序设计语言中规则更复杂,只不过包含了更多具有不同类型的字符。 
    基于属性的标识符语法(property-based identifier syntax) 
    这 里提供的正式语法就是要明确,一个标识符是由一个字母或者一个表意字符开始,包含任意数目的字母、表意字符、数字或下划线的字符串组成的。每种程序设计语 言标准都有自己的标识符语法,不同程序设计语言对ASCII范围内特定字符的使用有不同的约定。对这些语法进行扩充以具备Unicode实现的全部行为, 只需要讲这些特定规则与下面提供的样本语法结合。 
    为了正确的涵盖Unicode标准,样本标识符语法中的革新之处包括: 
      结合对组合标记的恰当处理。 
      允许有布局和格式控制字符,在解析标识符时忽略。 
    组合标记(combining marks) 
    标识符语法中必须考虑组合标记。由一个基字符跟随若干组合标记组成组合字符序列对一个标识符而言是有效的。 
    封闭的组合标记被排除在的语法定义外,因为由它们和字母所组合得到的组合字符不是这些标识符有效的组成部分。 
    布局和格式控制字符(layout and format control character) 
    用 于控制组合行为,双向顺序控制和可选显示格式的Unicode字符,被明确定义为不影响中断行为。不像空格符或其他分隔符,它们不用来指示词、行或其他单 元的边界。因而,为了标识符定义,将它们明确包括在内。一些实现可能选择过滤掉这些可忽略字符,这种方法的优点在于两个显示相同的标识符更可能是相同的。 
    特殊字符调整(specific character adjustments) 
    特殊的标识符语法可以被看作是基于字符属性对普通语法的少量修改。例如, SQL标识符允许下划线作为标识符的一部分(但不能作为开始字符);而C标识符允许既下划线作为标识符的一部分也可以作为标识符的开始字符。 
    可以考虑排除在标识符外的字符集合包括所有兼容映射具有标记的字符。 
    语法规则(Synactic Rule) 
    := (| 
    )* 
    Sytactic Classes for Identifiers

    Syntactic Class Properties 
    General Category = L or Nl, or 
    Other_ID_Start = true 
    General Category = Mn, Mc, or Nd, Pc, or Cf 
    可选建议(Alternative Recommendation) 
    使用语法类别不足之处是,用于详细定义的存储空间,以及随着新版本Unicode标准添加的新字符无法被已有的解析器识别。也就是说,无法做到向上兼容。 
    解决该问题的一个方法是,不去定义允许使用的码点集合,而是将一个较小的固定的码点集合保留给语法使用并且允许使用其他任何码点(包括非分配的码点)用作标识符的一部分。按照这种规范编写的解析器对任何版本的Unicode标准得表现相同。 
    这种方法的缺点是标识符中部分可能是没有意义的东西,因为将词汇分类与人类的可理解性分开了。然而,可理解性可以通过其他方法解决,如使用用法指南限定使用有意义的术语。例如W3C指定的规范XML 1.1。 
    通 过增加不允许使用字符的集合,可以得到针对标识符较直观的建议。这种方法使用Unicode标准一个特定版本中关于标识符类别的所有规范,并且永远不允许 使用该版本中不推荐用作标识符的字符。该版本Unicode标准中没有分配的所有码点可用于标识符,已经考虑到将来对版本的添加。这种方法保证了向上兼容 的标识符稳定性,以及将字符合理地划分为具有或不具有意义的标识符组成。 
    可以对禁止使用的码点列表进行一些额外的扩充,来进一步限制不合理的标识符。 
    4.16 排序和查找 
    排 序和查找操作部分相一致,都要实现相互比较项的等价程度判定。在查找操作中,等价定义项是否匹配;在排序操作中,等价影响项在有序队列中的邻近。等价的确 定经常依赖于应用和语言,但对于支持Unicode标准的实现而言,排序和查找必须考虑到Unicode字符的等价性和规范顺序。 
    与语言文化有关的排序和查找 
    排 序顺序随着文化的不同而变化,并且一些特殊的应用需要变化。排序的顺序可以依据词或者句子,区分大小写或者不分大小写,忽略重音符或者不忽略;也可以是依 据语音,或者基于字符的外观,比如使用笔划和部首对东亚的表意字符排序。对汉字的语音排序需要使用词语的查找词典,或者是可以维持文本中词和相关语音拼写 的特殊程序。 
    语言不仅决定使用哪一种排序,而且决定什么构成排序的基本元素。例如,瑞典语中将U+00C4 LATINE CAPITAL LETTER A WITH DIAERESIS作为一个单独的字母,在字母表中排在z之后;然而,在德语中,则作为ae或者识跟随在a之后的其他重音形式。西班牙语在传统上将连字 ll看作在l和m之间的字母来排序。 
    因此,不可能在编码时以某种顺序安排字符以便通过简单的二进制串比交接可以生成期待的顺序,也不可能提供单级的排序权重表。后者意味着字符编码细节对文化上期待的排序只具有间接的影响。 
    与语言无关的排序 
    在 一些环境下,应用程序可能需要进行与语言无关的排序,即对文本数据排序,而不考虑针对串如何排序的与语言相关的文化期望。例如,一个临时的索引可能只需要 以某些定义良好的顺序排列,但排序的准确细节并不重要或者对用户不可见。然而,即使在这种情况下,也需要注意一些问题。 
    首先,三种Unicode编码格式的二进制排序存在一些细微的差别。只需要对Unicode串进行二进制比较的实现必须考虑这一点,不至于在使用不同编码格式的应用程序间引起互操作问题。 
    一些排序或者查找应用,即使不关心排序中与语言相关的差别,也要求与大小写无关。传统上,执行与大小写无关比较的实现是通过在二进制比较前将两个串都转换为大写的形式来完成的。然而,这种方法一般不能扩展到Unicode标准中的所有字符。 
    查找 
    查找也受比较操作中一些同样的问题影响。也增加了其他一些特征,如只匹配词(即在匹配的两边都是词的边界)。一种技术是针对一个弱匹配进行快速查找。当发现一个候选匹配时,根据其他标准(如匹配变音符,词匹配,大小写匹配等等)。 
    当 查找串时,必须检查目标串中尾随的非间距标记,可能影响最后一个匹配字符的解释。也就是,查找"San Jose"可能会在串"Visiting San José, Costa Rica is a ..."发现一个匹配。如果要求准确的匹配,则应该否决该匹配。如果只要求弱匹配,则可以接受该匹配,但是在返回目标字串的位置和长度时必须包括尾随的非 间距标记。 
    弱等价的一个重要应用是与大小写无关的检索。一些传统的实现将查找串和目标串都映射为大写。然而,大小写映射是依赖语言的,并且不是没有歧义。 
    因为从外部字符集的错误映射,产生一个相关问题。为了解决这个问题,可以将用户易搞混的字符归为一个弱匹配类。这种方法在查找命名的文件或其他对象时可以更好的满足用户的语气。 
    次线性查找(Sublinear Searching) 
    使用比较信息,通过硬算(brute force),国际化的查找是可能的。然而,这种策略在最坏情况下需要O(m*n)算法,在一般情况下需要O(m)算法,n是所寻找的模式中字符的数目,m是目标串中的字符数。 
    一些算法可以使用次线性的算法对简单文本进行快速查找。通过在目标串中跳过字符,这些算法在通常情况下的复杂度只有O(m/n)。 
    在次线性查找中采用与语言有关的比较算法的主要问题,与多映射和可忽略有关。另外,次线性算法预先计算信息表。 
    4.17 二进制顺序 
    如果比较文本对最终用户是可见的,就应该使用正确的语言排序。然而,在有一些情况下,只需要一个快速的有良好定义的排序。在这种情况下,可以使用一个二进制排序。 
    Unicode 中的所有编码格式并没有相同的二进制顺序。UTF-8和UTF-32的数据以码点顺序排序,而UTF-16的数据(码点高于U+FFFF)则不是。而且, 当UTF-16或UTF-32数据使用某个Unicode模式序列化,并以字节比较时,得到的字节序列可能具有也可能没有相同的二进制排序,因为交换字节 顺序将影响数据的大体排序。由于这些因素,UTF-16BE、UTF-16LE、UTF-32LE编码方案下的文本不是以码点顺序排序。 
    一般,Unicode文本的却省二进制排列顺序应该是码点顺序。然而,可能需要与特定编码格式中的编码单元顺序(或是特定编码方案的字节排序)匹配,以便完成不同应用中使用的排序。 
    4.18 Case Mapping 
    Case 是特定字母表中字符的一个标准属性,比如Latin、Greek、Cyrillic、Armenian,和古代格鲁吉亚文,字符被认为是单个字母的变体。 这些变体在形状和大小上可能区别很大,称为大写字母和小写字母。一般大写字母比小写字母大。具有大小写差异的字母表称为bicameral;没有的则称为 unicameral。 
    为了兼容性还包含了某些组合字符,如U+01F1 "DZ" LATIN LETTER DZ,就有了第三种状态,称作titlecase,用于当词的第一个字符被大写时。这种字符的一个例子是U+01F2 "Dz" LATIN CAPITAL LETTER D WITH SMALL LETTER Z。 
    因此,三种状态形式为UPPERCASE、Titlecase和lowercase。 
    术语"titlecase"可用于指词语,它的第一个字母是一个大写字母或者是titlecase字母,其余字母为小写。然而,并不是所有在文档标题中的词或者句子中的第一个词都是titlecase。 
    决 定哪一个词是titlecase依赖于语言。例如"Taming of the Shrew"在英语中是适当的大写,但"Taming Of The Shrew"不是。而且,决定什么真正组成一个词是与语言相关的。例如,l'arbre在法语种可能被认为是两个词,但can't在英语种被认为是一个 词。 
    Case Mapping的困难 
    一旦字符集超出了ASCII的范围,case mapping就会有一些困难。 
    在多数情况下,titlecase与uppercase相同,但并不总是这样。例如,U+01F1 "DZ" capital dz的titlecase是U+01F2 "Dz" capital d with small z。 
    case mapping可能生成与源串的长度不同的串。例如,德文字符U+00DF LATIN SMALL LETTER SHARP S在转换成大写时扩张成两个字符的序列"SS"。这种情况也出现在没有预组合字符的情况下。 
    由一些字符需要特殊的处理,如U+0345 combining iota subscript。 
    依 赖上下文环境,字符也可能有不同的case mapping。例如,U+03A3 GREEK CAPITAL LETTER SIGMA,当后面跟随其他字母的时,对应的小写字符为U+03C3 GREEK SMALL LETTER SIGMA;没有跟其他字母时,对应小写字符为U+03C2 GREEK SMALL LETTER FINAL SIGMAL。 
    字符的case mapping可能依赖于地区。 
    由于一些字母实际上不分大小写,没有匹配的大写形式,因此,将一个串转换为大写的过程并不意味着不包括任何小写字母。 
    可逆性(Reversibility) 
    必须注意到,没有case转换操作时可逆的。例如: 
    toUpperCase(toLowerCase("John Brown")) -> "JOHN BROWN" 
    toLowerCase(toUpperCase("John Brown")) -> "john brown" 
    甚 至还有一些单个词,像意大利语中的vederLa或英语中的名字McGowan,既不是大写,也不是小写或titlecase。这种形式有时称作 inner-caps,通常用于程序设计和Web名称。一旦串"McGowan"被转换成大写、小写或titlecase,就不可能通过另一个大写、小写 或titlecase操作恢复原样。也存在单个的字符没有可逆的映射,如希腊文中的sigma。 
    对于使用单个命令键组成的序列在不同case间转换所选择内容的字处理软件,建议保存初始串,并且可以通过键序列返回初始串。用户界面要生成以下对一系列命令键响应的结果。注意,初始串每隔四次就会被存储。 
    1. The quick brown 
    2. THE QUICK BROWN 
    3. the quick brown 
    4. The Quick Brown 
    5. The quick brown 
    在字处理软件中,大写、小写和titlecase可以使用字符类型来表示。去除字符类型,就将文本恢复为初始状态。然而,如果采用这种方法,任何拼写检查软件必须注意case类型,以便可以对真正的外观进行检查。 
    不分大小写的匹配(Caseless Matching) 
    不分大小写的匹配是使用case folding实现的,该过程将串映射为一种消除了大小写差异的规范形式。Case folding顾及到查找中的不分大小写的快速匹配,因为只需要二进制比较。它不仅仅是只转换为小写形式。 
    通常,初始的串不会被转换的串替代,因为这样的替代可能会抹掉重要的信息。例如,名字"Marco di Silva"转换为"marco di silva",失去了关于哪个字母是大写的信息。 
    在Unicode Character Database(UCD)中的文件CaseFolding.txt用于执行与地区无关的case folding。该文件是通过单字符映射和多字符映射,从UCD中的case mapping生成的。它将所有具有不同case形式的字符转换成一个普通形式。对两个串进行不分大小写的比较时,可以利用这些数据对串进行转换,在使用 二进制比较。

    展开全文
  • 《信息交换用汉字编码字符集》是由中国国家标准总局1980年发布,1981年5月1日开始实施的一套国家标准标准号是GB2312-1980。GB2312编码适用于汉字处理、汉字通信等系统之间的信息交换,通行于中国大陆;新加坡等地...

    《信息交换用汉字编码字符集》是由中国国家标准总局1980年发布,1981年5月1日开始实施的一套国家标准,标准号是GB2312-1980。GB2312编码适用于汉字处理、汉字通信等系统之间的信息交换,通行于中国大陆;新加坡等地也采用此编码。中国大陆几乎所有的中文系统和国际化的软件都支持GB2312。
    GB2312标准共收录6763个汉字,其中一级汉字3755个,二级汉字3008个;同时,GB2312收录了包括拉丁字母、希腊字母、日文平假名及片假名字母、俄语西里尔字母在内的682个全角字符。GB2312的出现,基本满足了汉字的计算机处理需要,它所收录的汉字已经覆盖中国大陆99.75%的使用频率。对于人名、古汉语等方面出现的罕用字,GB2312不能处理,这导致了后来GBK及GB18030汉字字符集的出现。
    GB2312中对所收汉字进行了“分区”处理,每区含有94个汉字/符号。这种表示方式也称为区位码。01-09区为特殊符号;16-55区为一级汉字,按拼音排序;56-87区为二级汉字,按部首/笔画排序;10-15区及88-94区则未有编码。举例来说,“啊”字是GB2312之中的第一个汉字,它的区位码就是1601。
    在使用GB2312的程序中,通常采用EUC储存方法,以便兼容于ASCII。浏览器编码表上的“GB2312”,通常都是指“EUC-CN”表示法:每个汉字及符号以两个字节来表示,第一个字节称为“高位字节”(也称“区字节)”,第二个字节称为“低位字节”(也称“位字节”)。“高位字节”使用了0xA1-0xF7(把01-87区的区号加上0xA0),“低位字节”使用了0xA1-0xFE(把01-94加上 0xA0)。由于一级汉字从16区起始,汉字区的“高位字节”的范围是0xB0-0xF7,“低位字节”的范围是0xA1-0xFE,占用的码位是 72*94=6768,其中有5个空位是D7FA-D7FE。
    (附表中,每区第一个为空,第一行依次退一个格,如B0A0为空,第一个汉字“啊”内码为B0A1)
    code +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F
    A1A0   、 。 · ˉ ˇ ¨ 〃 々 — ~ ‖ … ‘ ’
    A1B0 “ ” 〔 〕 〈 〉 《 》 「 」 『 』 〖 〗 【 】
    A1C0 ± × ÷ ∶ ∧ ∨ ∑ ∏ ∪ ∩ ∈ ∷ √ ⊥ ∥ ∠
    A1D0 ⌒ ⊙ ∫ ∮ ≡ ≌ ≈ ∽ ∝ ≠ ≮ ≯ ≤ ≥ ∞ ∵
    A1E0 ∴ ♂ ♀ ° ′ ″ ℃ $ ¤ ¢ £ ‰ § № ☆ ★
    A1F0 ○ ● ◎ ◇ ◆ □ ■ △ ▲ ※ → ← ↑ ↓ 〓
    code +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F
    A2A0 ⅰ ⅱ ⅲ ⅳ ⅴ ⅵ ⅶ ⅷ ⅸ ⅹ     
    A2B0  ⒈ ⒉ ⒊ ⒋ ⒌ ⒍ ⒎ ⒏ ⒐ ⒑ ⒒ ⒓ ⒔ ⒕ ⒖
    A2C0 ⒗ ⒘ ⒙ ⒚ ⒛ ⑴ ⑵ ⑶ ⑷ ⑸ ⑹ ⑺ ⑻ ⑼ ⑽ ⑾
    A2D0 ⑿ ⒀ ⒁ ⒂ ⒃ ⒄ ⒅ ⒆ ⒇ ① ② ③ ④ ⑤ ⑥ ⑦
    A2E0 ⑧ ⑨ ⑩   ㈠ ㈡ ㈢ ㈣ ㈤ ㈥ ㈦ ㈧ ㈨ ㈩ 
    A2F0  Ⅰ Ⅱ Ⅲ Ⅳ Ⅴ Ⅵ Ⅶ Ⅷ Ⅸ Ⅹ Ⅺ Ⅻ  
    code +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F
    A3A0 ! " # ¥ % & ' ( ) * + , - . /
    A3B0 0 1 2 3 4 5 6 7 8 9 : ; < = > ?
    A3C0 @ A B C D E F G H I J K L M N O
    A3D0 P Q R S T U V W X Y Z [ \ ] ^ _
    A3E0 ` a b c d e f g h i j k l m n o
    A3F0 p q r s t u v w x y z { | }  ̄
    code +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F
    A4A0 ぁ あ ぃ い ぅ う ぇ え ぉ お か が き ぎ く
    A4B0 ぐ け げ こ ご さ ざ し じ す ず せ ぜ そ ぞ た
    A4C0 だ ち ぢ っ つ づ て で と ど な に ぬ ね の は
    A4D0 ば ぱ ひ び ぴ ふ ぶ ぷ へ べ ぺ ほ ぼ ぽ ま み
    A4E0 む め も ゃ や ゅ ゆ ょ よ ら り る れ ろ ゎ わ
    A4F0 ゐ ゑ を ん           
    code +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F
    A5A0 ァ ア ィ イ ゥ ウ ェ エ ォ オ カ ガ キ ギ ク
    A5B0 グ ケ ゲ コ ゴ サ ザ シ ジ ス ズ セ ゼ ソ ゾ タ
    A5C0 ダ チ ヂ ッ ツ ヅ テ デ ト ド ナ ニ ヌ ネ ノ ハ
    A5D0 バ パ ヒ ビ ピ フ ブ プ ヘ ベ ペ ホ ボ ポ マ ミ
    A5E0 ム メ モ ャ ヤ ュ ユ ョ ヨ ラ リ ル レ ロ ヮ ワ
    A5F0 ヰ ヱ ヲ ン ヴ ヵ ヶ        
    code +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F
    A6A0 Α Β Γ Δ Ε Ζ Η Θ Ι Κ Λ Μ Ν Ξ Ο
    A6B0 Π Ρ Σ Τ Υ Φ Χ Ψ Ω       
    A6C0  α β γ δ ε ζ η θ ι κ λ μ ν ξ ο
    A6D0 π ρ σ τ υ φ χ ψ ω       
    A6E0 ︵ ︶ ︹ ︺ ︿ ﹀ ︽ ︾ ﹁ ﹂ ﹃ ﹄   ︻ ︼
    A6F0 ︷ ︸ ︱  ︳ ︴         
    code +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F
    A7A0 А Б В Г Д Е Ё Ж З И Й К Л М Н
    A7B0 О П Р С Т У Ф Х Ц Ч Ш Щ Ъ Ы Ь Э
    A7C0 Ю Я              
    A7D0  а б в г д е ё ж з и й к л м н
    A7E0 о п р с т у ф х ц ч ш щ ъ ы ь э
    A7F0 ю я             
    code +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F
    A8A0 ā á ǎ à ē é ě è ī í ǐ ì ō ó ǒ
    A8B0 ò ū ú ǔ ù ǖ ǘ ǚ ǜ ü ê ɑ  ń ň ǹ
    A8C0 ɡ     ㄅ ㄆ ㄇ ㄈ ㄉ ㄊ ㄋ ㄌ ㄍ ㄎ ㄏ
    A8D0 ㄐ ㄑ ㄒ ㄓ ㄔ ㄕ ㄖ ㄗ ㄘ ㄙ ㄚ ㄛ ㄜ ㄝ ㄞ ㄟ
    A8E0 ㄠ ㄡ ㄢ ㄣ ㄤ ㄥ ㄦ ㄧ ㄨ ㄩ      
    A8F0               
    code +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F
    A9A0    ─ ━ │ ┃ ┄ ┅ ┆ ┇ ┈ ┉ ┊ ┋
    A9B0 ┌ ┍ ┎ ┏ ┐ ┑ ┒ ┓ └ ┕ ┖ ┗ ┘ ┙ ┚ ┛
    A9C0 ├ ┝ ┞ ┟ ┠ ┡ ┢ ┣ ┤ ┥ ┦ ┧ ┨ ┩ ┪ ┫
    A9D0 ┬ ┭ ┮ ┯ ┰ ┱ ┲ ┳ ┴ ┵ ┶ ┷ ┸ ┹ ┺ ┻
    A9E0 ┼ ┽ ┾ ┿ ╀ ╁ ╂ ╃ ╄ ╅ ╆ ╇ ╈ ╉ ╊ ╋
    A9F0               
    code +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F
    B0A0 啊 阿 埃 挨 哎 唉 哀 皑 癌 蔼 矮 艾 碍 爱 隘
    B0B0 鞍 氨 安 俺 按 暗 岸 胺 案 肮 昂 盎 凹 敖 熬 翱
    B0C0 袄 傲 奥 懊 澳 芭 捌 扒 叭 吧 笆 八 疤 巴 拔 跋
    B0D0 靶 把 耙 坝 霸 罢 爸 白 柏 百 摆 佰 败 拜 稗 斑
    B0E0 班 搬 扳 般 颁 板 版 扮 拌 伴 瓣 半 办 绊 邦 帮
    B0F0 梆 榜 膀 绑 棒 磅 蚌 镑 傍 谤 苞 胞 包 褒 剥
    code +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F
    B1A0 薄 雹 保 堡 饱 宝 抱 报 暴 豹 鲍 爆 杯 碑 悲
    B1B0 卑 北 辈 背 贝 钡 倍 狈 备 惫 焙 被 奔 苯 本 笨
    B1C0 崩 绷 甭 泵 蹦 迸 逼 鼻 比 鄙 笔 彼 碧 蓖 蔽 毕
    B1D0 毙 毖 币 庇 痹 闭 敝 弊 必 辟 壁 臂 避 陛 鞭 边
    B1E0 编 贬 扁 便 变 卞 辨 辩 辫 遍 标 彪 膘 表 鳖 憋
    B1F0 别 瘪 彬 斌 濒 滨 宾 摈 兵 冰 柄 丙 秉 饼 炳
    code +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F
    B2A0 病 并 玻 菠 播 拨 钵 波 博 勃 搏 铂 箔 伯 帛
    B2B0 舶 脖 膊 渤 泊 驳 捕 卜 哺 补 埠 不 布 步 簿 部
    B2C0 怖 擦 猜 裁 材 才 财 睬 踩 采 彩 菜 蔡 餐 参 蚕
    B2D0 残 惭 惨 灿 苍 舱 仓 沧 藏 操 糙 槽 曹 草 厕 策
    B2E0 侧 册 测 层 蹭 插 叉 茬 茶 查 碴 搽 察 岔 差 诧
    B2F0 拆 柴 豺 搀 掺 蝉 馋 谗 缠 铲 产 阐 颤 昌 猖
    code +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F
    B3A0 场 尝 常 长 偿 肠 厂 敞 畅 唱 倡 超 抄 钞 朝
    B3B0 嘲 潮 巢 吵 炒 车 扯 撤 掣 彻 澈 郴 臣 辰 尘 晨
    B3C0 忱 沉 陈 趁 衬 撑 称 城 橙 成 呈 乘 程 惩 澄 诚
    B3D0 承 逞 骋 秤 吃 痴 持 匙 池 迟 弛 驰 耻 齿 侈 尺
    B3E0 赤 翅 斥 炽 充 冲 虫 崇 宠 抽 酬 畴 踌 稠 愁 筹
    B3F0 仇 绸 瞅 丑 臭 初 出 橱 厨 躇 锄 雏 滁 除 楚
    code +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F
    B4A0 础 储 矗 搐 触 处 揣 川 穿 椽 传 船 喘 串 疮
    B4B0 窗 幢 床 闯 创 吹 炊 捶 锤 垂 春 椿 醇 唇 淳 纯
    B4C0 蠢 戳 绰 疵 茨 磁 雌 辞 慈 瓷 词 此 刺 赐 次 聪
    B4D0 葱 囱 匆 从 丛 凑 粗 醋 簇 促 蹿 篡 窜 摧 崔 催
    B4E0 脆 瘁 粹 淬 翠 村 存 寸 磋 撮 搓 措 挫 错 搭 达
    B4F0 答 瘩 打 大 呆 歹 傣 戴 带 殆 代 贷 袋 待 逮
    code +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F
    B5A0 怠 耽 担 丹 单 郸 掸 胆 旦 氮 但 惮 淡 诞 弹
    B5B0 蛋 当 挡 党 荡 档 刀 捣 蹈 倒 岛 祷 导 到 稻 悼
    B5C0 道 盗 德 得 的 蹬 灯 登 等 瞪 凳 邓 堤 低 滴 迪
    B5D0 敌 笛 狄 涤 翟 嫡 抵 底 地 蒂 第 帝 弟 递 缔 颠
    B5E0 掂 滇 碘 点 典 靛 垫 电 佃 甸 店 惦 奠 淀 殿 碉
    B5F0 叼 雕 凋 刁 掉 吊 钓 调 跌 爹 碟 蝶 迭 谍 叠
    code +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F
    B6A0 丁 盯 叮 钉 顶 鼎 锭 定 订 丢 东 冬 董 懂 动
    B6B0 栋 侗 恫 冻 洞 兜 抖 斗 陡 豆 逗 痘 都 督 毒 犊
    B6C0 独 读 堵 睹 赌 杜 镀 肚 度 渡 妒 端 短 锻 段 断
    B6D0 缎 堆 兑 队 对 墩 吨 蹲 敦 顿 囤 钝 盾 遁 掇 哆
    B6E0 多 夺 垛 躲 朵 跺 舵 剁 惰 堕 蛾 峨 鹅 俄 额 讹
    B6F0 娥 恶 厄 扼 遏 鄂 饿 恩 而 儿 耳 尔 饵 洱 二
    code +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F
    B7A0 贰 发 罚 筏 伐 乏 阀 法 珐 藩 帆 番 翻 樊 矾
    B7B0 钒 繁 凡 烦 反 返 范 贩 犯 饭 泛 坊 芳 方 肪 房
    B7C0 防 妨 仿 访 纺 放 菲 非 啡 飞 肥 匪 诽 吠 肺 废
    B7D0 沸 费 芬 酚 吩 氛 分 纷 坟 焚 汾 粉 奋 份 忿 愤
    B7E0 粪 丰 封 枫 蜂 峰 锋 风 疯 烽 逢 冯 缝 讽 奉 凤
    B7F0 佛 否 夫 敷 肤 孵 扶 拂 辐 幅 氟 符 伏 俘 服
    code +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F
    B8A0 浮 涪 福 袱 弗 甫 抚 辅 俯 釜 斧 脯 腑 府 腐
    B8B0 赴 副 覆 赋 复 傅 付 阜 父 腹 负 富 讣 附 妇 缚
    B8C0 咐 噶 嘎 该 改 概 钙 盖 溉 干 甘 杆 柑 竿 肝 赶
    B8D0 感 秆 敢 赣 冈 刚 钢 缸 肛 纲 岗 港 杠 篙 皋 高
    B8E0 膏 羔 糕 搞 镐 稿 告 哥 歌 搁 戈 鸽 胳 疙 割 革
    B8F0 葛 格 蛤 阁 隔 铬 个 各 给 根 跟 耕 更 庚 羹
    code +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F
    B9A0 埂 耿 梗 工 攻 功 恭 龚 供 躬 公 宫 弓 巩 汞
    B9B0 拱 贡 共 钩 勾 沟 苟 狗 垢 构 购 够 辜 菇 咕 箍
    B9C0 估 沽 孤 姑 鼓 古 蛊 骨 谷 股 故 顾 固 雇 刮 瓜
    B9D0 剐 寡 挂 褂 乖 拐 怪 棺 关 官 冠 观 管 馆 罐 惯
    B9E0 灌 贯 光 广 逛 瑰 规 圭 硅 归 龟 闺 轨 鬼 诡 癸
    B9F0 桂 柜 跪 贵 刽 辊 滚 棍 锅 郭 国 果 裹 过 哈
    code +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F
    BAA0 骸 孩 海 氦 亥 害 骇 酣 憨 邯 韩 含 涵 寒 函
    BAB0 喊 罕 翰 撼 捍 旱 憾 悍 焊 汗 汉 夯 杭 航 壕 嚎
    BAC0 豪 毫 郝 好 耗 号 浩 呵 喝 荷 菏 核 禾 和 何 合
    BAD0 盒 貉 阂 河 涸 赫 褐 鹤 贺 嘿 黑 痕 很 狠 恨 哼
    BAE0 亨 横 衡 恒 轰 哄 烘 虹 鸿 洪 宏 弘 红 喉 侯 猴
    BAF0 吼 厚 候 后 呼 乎 忽 瑚 壶 葫 胡 蝴 狐 糊 湖
    code +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F
    BBA0 弧 虎 唬 护 互 沪 户 花 哗 华 猾 滑 画 划 化
    BBB0 话 槐 徊 怀 淮 坏 欢 环 桓 还 缓 换 患 唤 痪 豢
    BBC0 焕 涣 宦 幻 荒 慌 黄 磺 蝗 簧 皇 凰 惶 煌 晃 幌
    BBD0 恍 谎 灰 挥 辉 徽 恢 蛔 回 毁 悔 慧 卉 惠 晦 贿
    BBE0 秽 会 烩 汇 讳 诲 绘 荤 昏 婚 魂 浑 混 豁 活 伙
    BBF0 火 获 或 惑 霍 货 祸 击 圾 基 机 畸 稽 积 箕
    code +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F
    BCA0 肌 饥 迹 激 讥 鸡 姬 绩 缉 吉 极 棘 辑 籍 集
    BCB0 及 急 疾 汲 即 嫉 级 挤 几 脊 己 蓟 技 冀 季 伎
    BCC0 祭 剂 悸 济 寄 寂 计 记 既 忌 际 妓 继 纪 嘉 枷
    BCD0 夹 佳 家 加 荚 颊 贾 甲 钾 假 稼 价 架 驾 嫁 歼
    BCE0 监 坚 尖 笺 间 煎 兼 肩 艰 奸 缄 茧 检 柬 碱 硷
    BCF0 拣 捡 简 俭 剪 减 荐 槛 鉴 践 贱 见 键 箭 件
    code +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F
    BDA0 健 舰 剑 饯 渐 溅 涧 建 僵 姜 将 浆 江 疆 蒋
    BDB0 桨 奖 讲 匠 酱 降 蕉 椒 礁 焦 胶 交 郊 浇 骄 娇
    BDC0 嚼 搅 铰 矫 侥 脚 狡 角 饺 缴 绞 剿 教 酵 轿 较
    BDD0 叫 窖 揭 接 皆 秸 街 阶 截 劫 节 桔 杰 捷 睫 竭
    BDE0 洁 结 解 姐 戒 藉 芥 界 借 介 疥 诫 届 巾 筋 斤
    BDF0 金 今 津 襟 紧 锦 仅 谨 进 靳 晋 禁 近 烬 浸
    code +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F
    BEA0 尽 劲 荆 兢 茎 睛 晶 鲸 京 惊 精 粳 经 井 警
    BEB0 景 颈 静 境 敬 镜 径 痉 靖 竟 竞 净 炯 窘 揪 究
    BEC0 纠 玖 韭 久 灸 九 酒 厩 救 旧 臼 舅 咎 就 疚 鞠
    BED0 拘 狙 疽 居 驹 菊 局 咀 矩 举 沮 聚 拒 据 巨 具
    BEE0 距 踞 锯 俱 句 惧 炬 剧 捐 鹃 娟 倦 眷 卷 绢 撅
    BEF0 攫 抉 掘 倔 爵 觉 决 诀 绝 均 菌 钧 军 君 峻
    code +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F
    BFA0 俊 竣 浚 郡 骏 喀 咖 卡 咯 开 揩 楷 凯 慨 刊
    BFB0 堪 勘 坎 砍 看 康 慷 糠 扛 抗 亢 炕 考 拷 烤 靠
    BFC0 坷 苛 柯 棵 磕 颗 科 壳 咳 可 渴 克 刻 客 课 肯
    BFD0 啃 垦 恳 坑 吭 空 恐 孔 控 抠 口 扣 寇 枯 哭 窟
    BFE0 苦 酷 库 裤 夸 垮 挎 跨 胯 块 筷 侩 快 宽 款 匡
    BFF0 筐 狂 框 矿 眶 旷 况 亏 盔 岿 窥 葵 奎 魁 傀
    code +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F
    C0A0 馈 愧 溃 坤 昆 捆 困 括 扩 廓 阔 垃 拉 喇 蜡
    C0B0 腊 辣 啦 莱 来 赖 蓝 婪 栏 拦 篮 阑 兰 澜 谰 揽
    C0C0 览 懒 缆 烂 滥 琅 榔 狼 廊 郎 朗 浪 捞 劳 牢 老
    C0D0 佬 姥 酪 烙 涝 勒 乐 雷 镭 蕾 磊 累 儡 垒 擂 肋
    C0E0 类 泪 棱 楞 冷 厘 梨 犁 黎 篱 狸 离 漓 理 李 里
    C0F0 鲤 礼 莉 荔 吏 栗 丽 厉 励 砾 历 利 傈 例 俐
    code +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F
    C1A0 痢 立 粒 沥 隶 力 璃 哩 俩 联 莲 连 镰 廉 怜
    C1B0 涟 帘 敛 脸 链 恋 炼 练 粮 凉 梁 粱 良 两 辆 量
    C1C0 晾 亮 谅 撩 聊 僚 疗 燎 寥 辽 潦 了 撂 镣 廖 料
    C1D0 列 裂 烈 劣 猎 琳 林 磷 霖 临 邻 鳞 淋 凛 赁 吝
    C1E0 拎 玲 菱 零 龄 铃 伶 羚 凌 灵 陵 岭 领 另 令 溜
    C1F0 琉 榴 硫 馏 留 刘 瘤 流 柳 六 龙 聋 咙 笼 窿
    code +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F
    C2A0 隆 垄 拢 陇 楼 娄 搂 篓 漏 陋 芦 卢 颅 庐 炉
    C2B0 掳 卤 虏 鲁 麓 碌 露 路 赂 鹿 潞 禄 录 陆 戮 驴
    C2C0 吕 铝 侣 旅 履 屡 缕 虑 氯 律 率 滤 绿 峦 挛 孪
    C2D0 滦 卵 乱 掠 略 抡 轮 伦 仑 沦 纶 论 萝 螺 罗 逻
    C2E0 锣 箩 骡 裸 落 洛 骆 络 妈 麻 玛 码 蚂 马 骂 嘛
    C2F0 吗 埋 买 麦 卖 迈 脉 瞒 馒 蛮 满 蔓 曼 慢 漫
    code +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F
    C3A0 谩 芒 茫 盲 氓 忙 莽 猫 茅 锚 毛 矛 铆 卯 茂
    C3B0 冒 帽 貌 贸 么 玫 枚 梅 酶 霉 煤 没 眉 媒 镁 每
    C3C0 美 昧 寐 妹 媚 门 闷 们 萌 蒙 檬 盟 锰 猛 梦 孟
    C3D0 眯 醚 靡 糜 迷 谜 弥 米 秘 觅 泌 蜜 密 幂 棉 眠
    C3E0 绵 冕 免 勉 娩 缅 面 苗 描 瞄 藐 秒 渺 庙 妙 蔑
    C3F0 灭 民 抿 皿 敏 悯 闽 明 螟 鸣 铭 名 命 谬 摸
    code +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F
    C4A0 摹 蘑 模 膜 磨 摩 魔 抹 末 莫 墨 默 沫 漠 寞
    C4B0 陌 谋 牟 某 拇 牡 亩 姆 母 墓 暮 幕 募 慕 木 目
    C4C0 睦 牧 穆 拿 哪 呐 钠 那 娜 纳 氖 乃 奶 耐 奈 南
    C4D0 男 难 囊 挠 脑 恼 闹 淖 呢 馁 内 嫩 能 妮 霓 倪
    C4E0 泥 尼 拟 你 匿 腻 逆 溺 蔫 拈 年 碾 撵 捻 念 娘
    C4F0 酿 鸟 尿 捏 聂 孽 啮 镊 镍 涅 您 柠 狞 凝 宁
    code +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F
    C5A0 拧 泞 牛 扭 钮 纽 脓 浓 农 弄 奴 努 怒 女 暖
    C5B0 虐 疟 挪 懦 糯 诺 哦 欧 鸥 殴 藕 呕 偶 沤 啪 趴
    C5C0 爬 帕 怕 琶 拍 排 牌 徘 湃 派 攀 潘 盘 磐 盼 畔
    C5D0 判 叛 乓 庞 旁 耪 胖 抛 咆 刨 炮 袍 跑 泡 呸 胚
    C5E0 培 裴 赔 陪 配 佩 沛 喷 盆 砰 抨 烹 澎 彭 蓬 棚
    C5F0 硼 篷 膨 朋 鹏 捧 碰 坯 砒 霹 批 披 劈 琵 毗
    code +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F
    C6A0 啤 脾 疲 皮 匹 痞 僻 屁 譬 篇 偏 片 骗 飘 漂
    C6B0 瓢 票 撇 瞥 拼 频 贫 品 聘 乒 坪 苹 萍 平 凭 瓶
    C6C0 评 屏 坡 泼 颇 婆 破 魄 迫 粕 剖 扑 铺 仆 莆 葡
    C6D0 菩 蒲 埔 朴 圃 普 浦 谱 曝 瀑 期 欺 栖 戚 妻 七
    C6E0 凄 漆 柒 沏 其 棋 奇 歧 畦 崎 脐 齐 旗 祈 祁 骑
    C6F0 起 岂 乞 企 启 契 砌 器 气 迄 弃 汽 泣 讫 掐
    code +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F
    C7A0 恰 洽 牵 扦 钎 铅 千 迁 签 仟 谦 乾 黔 钱 钳
    C7B0 前 潜 遣 浅 谴 堑 嵌 欠 歉 枪 呛 腔 羌 墙 蔷 强
    C7C0 抢 橇 锹 敲 悄 桥 瞧 乔 侨 巧 鞘 撬 翘 峭 俏 窍
    C7D0 切 茄 且 怯 窃 钦 侵 亲 秦 琴 勤 芹 擒 禽 寝 沁
    C7E0 青 轻 氢 倾 卿 清 擎 晴 氰 情 顷 请 庆 琼 穷 秋
    C7F0 丘 邱 球 求 囚 酋 泅 趋 区 蛆 曲 躯 屈 驱 渠
    code +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F
    C8A0 取 娶 龋 趣 去 圈 颧 权 醛 泉 全 痊 拳 犬 券
    C8B0 劝 缺 炔 瘸 却 鹊 榷 确 雀 裙 群 然 燃 冉 染 瓤
    C8C0 壤 攘 嚷 让 饶 扰 绕 惹 热 壬 仁 人 忍 韧 任 认
    C8D0 刃 妊 纫 扔 仍 日 戎 茸 蓉 荣 融 熔 溶 容 绒 冗
    C8E0 揉 柔 肉 茹 蠕 儒 孺 如 辱 乳 汝 入 褥 软 阮 蕊
    C8F0 瑞 锐 闰 润 若 弱 撒 洒 萨 腮 鳃 塞 赛 三 叁
    code +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F
    C9A0 伞 散 桑 嗓 丧 搔 骚 扫 嫂 瑟 色 涩 森 僧 莎
    C9B0 砂 杀 刹 沙 纱 傻 啥 煞 筛 晒 珊 苫 杉 山 删 煽
    C9C0 衫 闪 陕 擅 赡 膳 善 汕 扇 缮 墒 伤 商 赏 晌 上
    C9D0 尚 裳 梢 捎 稍 烧 芍 勺 韶 少 哨 邵 绍 奢 赊 蛇
    C9E0 舌 舍 赦 摄 射 慑 涉 社 设 砷 申 呻 伸 身 深 娠
    C9F0 绅 神 沈 审 婶 甚 肾 慎 渗 声 生 甥 牲 升 绳
    code +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F
    CAA0 省 盛 剩 胜 圣 师 失 狮 施 湿 诗 尸 虱 十 石
    CAB0 拾 时 什 食 蚀 实 识 史 矢 使 屎 驶 始 式 示 士
    CAC0 世 柿 事 拭 誓 逝 势 是 嗜 噬 适 仕 侍 释 饰 氏
    CAD0 市 恃 室 视 试 收 手 首 守 寿 授 售 受 瘦 兽 蔬
    CAE0 枢 梳 殊 抒 输 叔 舒 淑 疏 书 赎 孰 熟 薯 暑 曙
    CAF0 署 蜀 黍 鼠 属 术 述 树 束 戍 竖 墅 庶 数 漱
    code +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F
    CBA0 恕 刷 耍 摔 衰 甩 帅 栓 拴 霜 双 爽 谁 水 睡
    CBB0 税 吮 瞬 顺 舜 说 硕 朔 烁 斯 撕 嘶 思 私 司 丝
    CBC0 死 肆 寺 嗣 四 伺 似 饲 巳 松 耸 怂 颂 送 宋 讼
    CBD0 诵 搜 艘 擞 嗽 苏 酥 俗 素 速 粟 僳 塑 溯 宿 诉
    CBE0 肃 酸 蒜 算 虽 隋 随 绥 髓 碎 岁 穗 遂 隧 祟 孙
    CBF0 损 笋 蓑 梭 唆 缩 琐 索 锁 所 塌 他 它 她 塔
    code +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F
    CCA0 獭 挞 蹋 踏 胎 苔 抬 台 泰 酞 太 态 汰 坍 摊
    CCB0 贪 瘫 滩 坛 檀 痰 潭 谭 谈 坦 毯 袒 碳 探 叹 炭
    CCC0 汤 塘 搪 堂 棠 膛 唐 糖 倘 躺 淌 趟 烫 掏 涛 滔
    CCD0 绦 萄 桃 逃 淘 陶 讨 套 特 藤 腾 疼 誊 梯 剔 踢
    CCE0 锑 提 题 蹄 啼 体 替 嚏 惕 涕 剃 屉 天 添 填 田
    CCF0 甜 恬 舔 腆 挑 条 迢 眺 跳 贴 铁 帖 厅 听 烃
    code +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F
    CDA0 汀 廷 停 亭 庭 挺 艇 通 桐 酮 瞳 同 铜 彤 童
    CDB0 桶 捅 筒 统 痛 偷 投 头 透 凸 秃 突 图 徒 途 涂
    CDC0 屠 土 吐 兔 湍 团 推 颓 腿 蜕 褪 退 吞 屯 臀 拖
    CDD0 托 脱 鸵 陀 驮 驼 椭 妥 拓 唾 挖 哇 蛙 洼 娃 瓦
    CDE0 袜 歪 外 豌 弯 湾 玩 顽 丸 烷 完 碗 挽 晚 皖 惋
    CDF0 宛 婉 万 腕 汪 王 亡 枉 网 往 旺 望 忘 妄 威
    code +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F
    CEA0 巍 微 危 韦 违 桅 围 唯 惟 为 潍 维 苇 萎 委
    CEB0 伟 伪 尾 纬 未 蔚 味 畏 胃 喂 魏 位 渭 谓 尉 慰
    CEC0 卫 瘟 温 蚊 文 闻 纹 吻 稳 紊 问 嗡 翁 瓮 挝 蜗
    CED0 涡 窝 我 斡 卧 握 沃 巫 呜 钨 乌 污 诬 屋 无 芜
    CEE0 梧 吾 吴 毋 武 五 捂 午 舞 伍 侮 坞 戊 雾 晤 物
    CEF0 勿 务 悟 误 昔 熙 析 西 硒 矽 晰 嘻 吸 锡 牺
    code +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F
    CFA0 稀 息 希 悉 膝 夕 惜 熄 烯 溪 汐 犀 檄 袭 席
    CFB0 习 媳 喜 铣 洗 系 隙 戏 细 瞎 虾 匣 霞 辖 暇 峡
    CFC0 侠 狭 下 厦 夏 吓 掀 锨 先 仙 鲜 纤 咸 贤 衔 舷
    CFD0 闲 涎 弦 嫌 显 险 现 献 县 腺 馅 羡 宪 陷 限 线
    CFE0 相 厢 镶 香 箱 襄 湘 乡 翔 祥 详 想 响 享 项 巷
    CFF0 橡 像 向 象 萧 硝 霄 削 哮 嚣 销 消 宵 淆 晓
    code +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F
    D0A0 小 孝 校 肖 啸 笑 效 楔 些 歇 蝎 鞋 协 挟 携
    D0B0 邪 斜 胁 谐 写 械 卸 蟹 懈 泄 泻 谢 屑 薪 芯 锌
    D0C0 欣 辛 新 忻 心 信 衅 星 腥 猩 惺 兴 刑 型 形 邢
    D0D0 行 醒 幸 杏 性 姓 兄 凶 胸 匈 汹 雄 熊 休 修 羞
    D0E0 朽 嗅 锈 秀 袖 绣 墟 戌 需 虚 嘘 须 徐 许 蓄 酗
    D0F0 叙 旭 序 畜 恤 絮 婿 绪 续 轩 喧 宣 悬 旋 玄
    code +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F
    D1A0 选 癣 眩 绚 靴 薛 学 穴 雪 血 勋 熏 循 旬 询
    D1B0 寻 驯 巡 殉 汛 训 讯 逊 迅 压 押 鸦 鸭 呀 丫 芽
    D1C0 牙 蚜 崖 衙 涯 雅 哑 亚 讶 焉 咽 阉 烟 淹 盐 严
    D1D0 研 蜒 岩 延 言 颜 阎 炎 沿 奄 掩 眼 衍 演 艳 堰
    D1E0 燕 厌 砚 雁 唁 彦 焰 宴 谚 验 殃 央 鸯 秧 杨 扬
    D1F0 佯 疡 羊 洋 阳 氧 仰 痒 养 样 漾 邀 腰 妖 瑶
    code +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F
    D2A0 摇 尧 遥 窑 谣 姚 咬 舀 药 要 耀 椰 噎 耶 爷
    D2B0 野 冶 也 页 掖 业 叶 曳 腋 夜 液 一 壹 医 揖 铱
    D2C0 依 伊 衣 颐 夷 遗 移 仪 胰 疑 沂 宜 姨 彝 椅 蚁
    D2D0 倚 已 乙 矣 以 艺 抑 易 邑 屹 亿 役 臆 逸 肄 疫
    D2E0 亦 裔 意 毅 忆 义 益 溢 诣 议 谊 译 异 翼 翌 绎
    D2F0 茵 荫 因 殷 音 阴 姻 吟 银 淫 寅 饮 尹 引 隐
    code +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F
    D3A0 印 英 樱 婴 鹰 应 缨 莹 萤 营 荧 蝇 迎 赢 盈
    D3B0 影 颖 硬 映 哟 拥 佣 臃 痈 庸 雍 踊 蛹 咏 泳 涌
    D3C0 永 恿 勇 用 幽 优 悠 忧 尤 由 邮 铀 犹 油 游 酉
    D3D0 有 友 右 佑 釉 诱 又 幼 迂 淤 于 盂 榆 虞 愚 舆
    D3E0 余 俞 逾 鱼 愉 渝 渔 隅 予 娱 雨 与 屿 禹 宇 语
    D3F0 羽 玉 域 芋 郁 吁 遇 喻 峪 御 愈 欲 狱 育 誉
    code +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F
    D4A0 浴 寓 裕 预 豫 驭 鸳 渊 冤 元 垣 袁 原 援 辕
    D4B0 园 员 圆 猿 源 缘 远 苑 愿 怨 院 曰 约 越 跃 钥
    D4C0 岳 粤 月 悦 阅 耘 云 郧 匀 陨 允 运 蕴 酝 晕 韵
    D4D0 孕 匝 砸 杂 栽 哉 灾 宰 载 再 在 咱 攒 暂 赞 赃
    D4E0 脏 葬 遭 糟 凿 藻 枣 早 澡 蚤 躁 噪 造 皂 灶 燥
    D4F0 责 择 则 泽 贼 怎 增 憎 曾 赠 扎 喳 渣 札 轧
    code +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F
    D5A0 铡 闸 眨 栅 榨 咋 乍 炸 诈 摘 斋 宅 窄 债 寨
    D5B0 瞻 毡 詹 粘 沾 盏 斩 辗 崭 展 蘸 栈 占 战 站 湛
    D5C0 绽 樟 章 彰 漳 张 掌 涨 杖 丈 帐 账 仗 胀 瘴 障
    D5D0 招 昭 找 沼 赵 照 罩 兆 肇 召 遮 折 哲 蛰 辙 者
    D5E0 锗 蔗 这 浙 珍 斟 真 甄 砧 臻 贞 针 侦 枕 疹 诊
    D5F0 震 振 镇 阵 蒸 挣 睁 征 狰 争 怔 整 拯 正 政
    code +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F
    D6A0 帧 症 郑 证 芝 枝 支 吱 蜘 知 肢 脂 汁 之 织
    D6B0 职 直 植 殖 执 值 侄 址 指 止 趾 只 旨 纸 志 挚
    D6C0 掷 至 致 置 帜 峙 制 智 秩 稚 质 炙 痔 滞 治 窒
    D6D0 中 盅 忠 钟 衷 终 种 肿 重 仲 众 舟 周 州 洲 诌
    D6E0 粥 轴 肘 帚 咒 皱 宙 昼 骤 珠 株 蛛 朱 猪 诸 诛
    D6F0 逐 竹 烛 煮 拄 瞩 嘱 主 著 柱 助 蛀 贮 铸 筑
    code +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F
    D7A0 住 注 祝 驻 抓 爪 拽 专 砖 转 撰 赚 篆 桩 庄
    D7B0 装 妆 撞 壮 状 椎 锥 追 赘 坠 缀 谆 准 捉 拙 卓
    D7C0 桌 琢 茁 酌 啄 着 灼 浊 兹 咨 资 姿 滋 淄 孜 紫
    D7D0 仔 籽 滓 子 自 渍 字 鬃 棕 踪 宗 综 总 纵 邹 走
    D7E0 奏 揍 租 足 卒 族 祖 诅 阻 组 钻 纂 嘴 醉 最 罪
    D7F0 尊 遵 昨 左 佐 柞 做 作 坐 座     
    code +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F
    D8A0 亍 丌 兀 丐 廿 卅 丕 亘 丞 鬲 孬 噩 丨 禺 丿
    D8B0 匕 乇 夭 爻 卮 氐 囟 胤 馗 毓 睾 鼗 丶 亟 鼐 乜
    D8C0 乩 亓 芈 孛 啬 嘏 仄 厍 厝 厣 厥 厮 靥 赝 匚 叵
    D8D0 匦 匮 匾 赜 卦 卣 刂 刈 刎 刭 刳 刿 剀 剌 剞 剡
    D8E0 剜 蒯 剽 劂 劁 劐 劓 冂 罔 亻 仃 仉 仂 仨 仡 仫
    D8F0 仞 伛 仳 伢 佤 仵 伥 伧 伉 伫 佞 佧 攸 佚 佝
    code +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F
    D9A0 佟 佗 伲 伽 佶 佴 侑 侉 侃 侏 佾 佻 侪 佼 侬
    D9B0 侔 俦 俨 俪 俅 俚 俣 俜 俑 俟 俸 倩 偌 俳 倬 倏
    D9C0 倮 倭 俾 倜 倌 倥 倨 偾 偃 偕 偈 偎 偬 偻 傥 傧
    D9D0 傩 傺 僖 儆 僭 僬 僦 僮 儇 儋 仝 氽 佘 佥 俎 龠
    D9E0 汆 籴 兮 巽 黉 馘 冁 夔 勹 匍 訇 匐 凫 夙 兕 亠
    D9F0 兖 亳 衮 袤 亵 脔 裒 禀 嬴 蠃 羸 冫 冱 冽 冼
    code +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F
    DAA0 凇 冖 冢 冥 讠 讦 讧 讪 讴 讵 讷 诂 诃 诋 诏
    DAB0 诎 诒 诓 诔 诖 诘 诙 诜 诟 诠 诤 诨 诩 诮 诰 诳
    DAC0 诶 诹 诼 诿 谀 谂 谄 谇 谌 谏 谑 谒 谔 谕 谖 谙
    DAD0 谛 谘 谝 谟 谠 谡 谥 谧 谪 谫 谮 谯 谲 谳 谵 谶
    DAE0 卩 卺 阝 阢 阡 阱 阪 阽 阼 陂 陉 陔 陟 陧 陬 陲
    DAF0 陴 隈 隍 隗 隰 邗 邛 邝 邙 邬 邡 邴 邳 邶 邺
    code +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F
    DBA0 邸 邰 郏 郅 邾 郐 郄 郇 郓 郦 郢 郜 郗 郛 郫
    DBB0 郯 郾 鄄 鄢 鄞 鄣 鄱 鄯 鄹 酃 酆 刍 奂 劢 劬 劭
    DBC0 劾 哿 勐 勖 勰 叟 燮 矍 廴 凵 凼 鬯 厶 弁 畚 巯
    DBD0 坌 垩 垡 塾 墼 壅 壑 圩 圬 圪 圳 圹 圮 圯 坜 圻
    DBE0 坂 坩 垅 坫 垆 坼 坻 坨 坭 坶 坳 垭 垤 垌 垲 埏
    DBF0 垧 垴 垓 垠 埕 埘 埚 埙 埒 垸 埴 埯 埸 埤 埝
    code +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F
    DCA0 堋 堍 埽 埭 堀 堞 堙 塄 堠 塥 塬 墁 墉 墚 墀
    DCB0 馨 鼙 懿 艹 艽 艿 芏 芊 芨 芄 芎 芑 芗 芙 芫 芸
    DCC0 芾 芰 苈 苊 苣 芘 芷 芮 苋 苌 苁 芩 芴 芡 芪 芟
    DCD0 苄 苎 芤 苡 茉 苷 苤 茏 茇 苜 苴 苒 苘 茌 苻 苓
    DCE0 茑 茚 茆 茔 茕 苠 苕 茜 荑 荛 荜 茈 莒 茼 茴 茱
    DCF0 莛 荞 茯 荏 荇 荃 荟 荀 茗 荠 茭 茺 茳 荦 荥
    code +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F
    DDA0 荨 茛 荩 荬 荪 荭 荮 莰 荸 莳 莴 莠 莪 莓 莜
    DDB0 莅 荼 莶 莩 荽 莸 荻 莘 莞 莨 莺 莼 菁 萁 菥 菘
    DDC0 堇 萘 萋 菝 菽 菖 萜 萸 萑 萆 菔 菟 萏 萃 菸 菹
    DDD0 菪 菅 菀 萦 菰 菡 葜 葑 葚 葙 葳 蒇 蒈 葺 蒉 葸
    DDE0 萼 葆 葩 葶 蒌 蒎 萱 葭 蓁 蓍 蓐 蓦 蒽 蓓 蓊 蒿
    DDF0 蒺 蓠 蒡 蒹 蒴 蒗 蓥 蓣 蔌 甍 蔸 蓰 蔹 蔟 蔺
    code +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F
    DEA0 蕖 蔻 蓿 蓼 蕙 蕈 蕨 蕤 蕞 蕺 瞢 蕃 蕲 蕻 薤
    DEB0 薨 薇 薏 蕹 薮 薜 薅 薹 薷 薰 藓 藁 藜 藿 蘧 蘅
    DEC0 蘩 蘖 蘼 廾 弈 夼 奁 耷 奕 奚 奘 匏 尢 尥 尬 尴
    DED0 扌 扪 抟 抻 拊 拚 拗 拮 挢 拶 挹 捋 捃 掭 揶 捱
    DEE0 捺 掎 掴 捭 掬 掊 捩 掮 掼 揲 揸 揠 揿 揄 揞 揎
    DEF0 摒 揆 掾 摅 摁 搋 搛 搠 搌 搦 搡 摞 撄 摭 撖
    code +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F
    DFA0 摺 撷 撸 撙 撺 擀 擐 擗 擤 擢 攉 攥 攮 弋 忒
    DFB0 甙 弑 卟 叱 叽 叩 叨 叻 吒 吖 吆 呋 呒 呓 呔 呖
    DFC0 呃 吡 呗 呙 吣 吲 咂 咔 呷 呱 呤 咚 咛 咄 呶 呦
    DFD0 咝 哐 咭 哂 咴 哒 咧 咦 哓 哔 呲 咣 哕 咻 咿 哌
    DFE0 哙 哚 哜 咩 咪 咤 哝 哏 哞 唛 哧 唠 哽 唔 哳 唢
    DFF0 唣 唏 唑 唧 唪 啧 喏 喵 啉 啭 啁 啕 唿 啐 唼
    code +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F
    E0A0 唷 啖 啵 啶 啷 唳 唰 啜 喋 嗒 喃 喱 喹 喈 喁
    E0B0 喟 啾 嗖 喑 啻 嗟 喽 喾 喔 喙 嗪 嗷 嗉 嘟 嗑 嗫
    E0C0 嗬 嗔 嗦 嗝 嗄 嗯 嗥 嗲 嗳 嗌 嗍 嗨 嗵 嗤 辔 嘞
    E0D0 嘈 嘌 嘁 嘤 嘣 嗾 嘀 嘧 嘭 噘 嘹 噗 嘬 噍 噢 噙
    E0E0 噜 噌 噔 嚆 噤 噱 噫 噻 噼 嚅 嚓 嚯 囔 囗 囝 囡
    E0F0 囵 囫 囹 囿 圄 圊 圉 圜 帏 帙 帔 帑 帱 帻 帼
    code +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F
    E1A0 帷 幄 幔 幛 幞 幡 岌 屺 岍 岐 岖 岈 岘 岙 岑
    E1B0 岚 岜 岵 岢 岽 岬 岫 岱 岣 峁 岷 峄 峒 峤 峋 峥
    E1C0 崂 崃 崧 崦 崮 崤 崞 崆 崛 嵘 崾 崴 崽 嵬 嵛 嵯
    E1D0 嵝 嵫 嵋 嵊 嵩 嵴 嶂 嶙 嶝 豳 嶷 巅 彳 彷 徂 徇
    E1E0 徉 後 徕 徙 徜 徨 徭 徵 徼 衢 彡 犭 犰 犴 犷 犸
    E1F0 狃 狁 狎 狍 狒 狨 狯 狩 狲 狴 狷 猁 狳 猃 狺
    code +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F
    E2A0 狻 猗 猓 猡 猊 猞 猝 猕 猢 猹 猥 猬 猸 猱 獐
    E2B0 獍 獗 獠 獬 獯 獾 舛 夥 飧 夤 夂 饣 饧 饨 饩 饪
    E2C0 饫 饬 饴 饷 饽 馀 馄 馇 馊 馍 馐 馑 馓 馔 馕 庀
    E2D0 庑 庋 庖 庥 庠 庹 庵 庾 庳 赓 廒 廑 廛 廨 廪 膺
    E2E0 忄 忉 忖 忏 怃 忮 怄 忡 忤 忾 怅 怆 忪 忭 忸 怙
    E2F0 怵 怦 怛 怏 怍 怩 怫 怊 怿 怡 恸 恹 恻 恺 恂
    code +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F
    E3A0 恪 恽 悖 悚 悭 悝 悃 悒 悌 悛 惬 悻 悱 惝 惘
    E3B0 惆 惚 悴 愠 愦 愕 愣 惴 愀 愎 愫 慊 慵 憬 憔 憧
    E3C0 憷 懔 懵 忝 隳 闩 闫 闱 闳 闵 闶 闼 闾 阃 阄 阆
    E3D0 阈 阊 阋 阌 阍 阏 阒 阕 阖 阗 阙 阚 丬 爿 戕 氵
    E3E0 汔 汜 汊 沣 沅 沐 沔 沌 汨 汩 汴 汶 沆 沩 泐 泔
    E3F0 沭 泷 泸 泱 泗 沲 泠 泖 泺 泫 泮 沱 泓 泯 泾
    code +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F
    E4A0 洹 洧 洌 浃 浈 洇 洄 洙 洎 洫 浍 洮 洵 洚 浏
    E4B0 浒 浔 洳 涑 浯 涞 涠 浞 涓 涔 浜 浠 浼 浣 渚 淇
    E4C0 淅 淞 渎 涿 淠 渑 淦 淝 淙 渖 涫 渌 涮 渫 湮 湎
    E4D0 湫 溲 湟 溆 湓 湔 渲 渥 湄 滟 溱 溘 滠 漭 滢 溥
    E4E0 溧 溽 溻 溷 滗 溴 滏 溏 滂 溟 潢 潆 潇 漤 漕 滹
    E4F0 漯 漶 潋 潴 漪 漉 漩 澉 澍 澌 潸 潲 潼 潺 濑
    code +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F
    E5A0 濉 澧 澹 澶 濂 濡 濮 濞 濠 濯 瀚 瀣 瀛 瀹 瀵
    E5B0 灏 灞 宀 宄 宕 宓 宥 宸 甯 骞 搴 寤 寮 褰 寰 蹇
    E5C0 謇 辶 迓 迕 迥 迮 迤 迩 迦 迳 迨 逅 逄 逋 逦 逑
    E5D0 逍 逖 逡 逵 逶 逭 逯 遄 遑 遒 遐 遨 遘 遢 遛 暹
    E5E0 遴 遽 邂 邈 邃 邋 彐 彗 彖 彘 尻 咫 屐 屙 孱 屣
    E5F0 屦 羼 弪 弩 弭 艴 弼 鬻 屮 妁 妃 妍 妩 妪 妣
    code +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F
    E6A0 妗 姊 妫 妞 妤 姒 妲 妯 姗 妾 娅 娆 姝 娈 姣
    E6B0 姘 姹 娌 娉 娲 娴 娑 娣 娓 婀 婧 婊 婕 娼 婢 婵
    E6C0 胬 媪 媛 婷 婺 媾 嫫 媲 嫒 嫔 媸 嫠 嫣 嫱 嫖 嫦
    E6D0 嫘 嫜 嬉 嬗 嬖 嬲 嬷 孀 尕 尜 孚 孥 孳 孑 孓 孢
    E6E0 驵 驷 驸 驺 驿 驽 骀 骁 骅 骈 骊 骐 骒 骓 骖 骘
    E6F0 骛 骜 骝 骟 骠 骢 骣 骥 骧 纟 纡 纣 纥 纨 纩
    code +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F
    E7A0 纭 纰 纾 绀 绁 绂 绉 绋 绌 绐 绔 绗 绛 绠 绡
    E7B0 绨 绫 绮 绯 绱 绲 缍 绶 绺 绻 绾 缁 缂 缃 缇 缈
    E7C0 缋 缌 缏 缑 缒 缗 缙 缜 缛 缟 缡 缢 缣 缤 缥 缦
    E7D0 缧 缪 缫 缬 缭 缯 缰 缱 缲 缳 缵 幺 畿 巛 甾 邕
    E7E0 玎 玑 玮 玢 玟 珏 珂 珑 玷 玳 珀 珉 珈 珥 珙 顼
    E7F0 琊 珩 珧 珞 玺 珲 琏 琪 瑛 琦 琥 琨 琰 琮 琬
    code +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F
    E8A0 琛 琚 瑁 瑜 瑗 瑕 瑙 瑷 瑭 瑾 璜 璎 璀 璁 璇
    E8B0 璋 璞 璨 璩 璐 璧 瓒 璺 韪 韫 韬 杌 杓 杞 杈 杩
    E8C0 枥 枇 杪 杳 枘 枧 杵 枨 枞 枭 枋 杷 杼 柰 栉 柘
    E8D0 栊 柩 枰 栌 柙 枵 柚 枳 柝 栀 柃 枸 柢 栎 柁 柽
    E8E0 栲 栳 桠 桡 桎 桢 桄 桤 梃 栝 桕 桦 桁 桧 桀 栾
    E8F0 桊 桉 栩 梵 梏 桴 桷 梓 桫 棂 楮 棼 椟 椠 棹
    code +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F
    E9A0 椤 棰 椋 椁 楗 棣 椐 楱 椹 楠 楂 楝 榄 楫 榀
    E9B0 榘 楸 椴 槌 榇 榈 槎 榉 楦 楣 楹 榛 榧 榻 榫 榭
    E9C0 槔 榱 槁 槊 槟 榕 槠 榍 槿 樯 槭 樗 樘 橥 槲 橄
    E9D0 樾 檠 橐 橛 樵 檎 橹 樽 樨 橘 橼 檑 檐 檩 檗 檫
    E9E0 猷 獒 殁 殂 殇 殄 殒 殓 殍 殚 殛 殡 殪 轫 轭 轱
    E9F0 轲 轳 轵 轶 轸 轷 轹 轺 轼 轾 辁 辂 辄 辇 辋
    code +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F
    EAA0 辍 辎 辏 辘 辚 軎 戋 戗 戛 戟 戢 戡 戥 戤 戬
    EAB0 臧 瓯 瓴 瓿 甏 甑 甓 攴 旮 旯 旰 昊 昙 杲 昃 昕
    EAC0 昀 炅 曷 昝 昴 昱 昶 昵 耆 晟 晔 晁 晏 晖 晡 晗
    EAD0 晷 暄 暌 暧 暝 暾 曛 曜 曦 曩 贲 贳 贶 贻 贽 赀
    EAE0 赅 赆 赈 赉 赇 赍 赕 赙 觇 觊 觋 觌 觎 觏 觐 觑
    EAF0 牮 犟 牝 牦 牯 牾 牿 犄 犋 犍 犏 犒 挈 挲 掰
    code +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F
    EBA0 搿 擘 耄 毪 毳 毽 毵 毹 氅 氇 氆 氍 氕 氘 氙
    EBB0 氚 氡 氩 氤 氪 氲 攵 敕 敫 牍 牒 牖 爰 虢 刖 肟
    EBC0 肜 肓 肼 朊 肽 肱 肫 肭 肴 肷 胧 胨 胩 胪 胛 胂
    EBD0 胄 胙 胍 胗 朐 胝 胫 胱 胴 胭 脍 脎 胲 胼 朕 脒
    EBE0 豚 脶 脞 脬 脘 脲 腈 腌 腓 腴 腙 腚 腱 腠 腩 腼
    EBF0 腽 腭 腧 塍 媵 膈 膂 膑 滕 膣 膪 臌 朦 臊 膻
    code +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F
    ECA0 臁 膦 欤 欷 欹 歃 歆 歙 飑 飒 飓 飕 飙 飚 殳
    ECB0 彀 毂 觳 斐 齑 斓 於 旆 旄 旃 旌 旎 旒 旖 炀 炜
    ECC0 炖 炝 炻 烀 炷 炫 炱 烨 烊 焐 焓 焖 焯 焱 煳 煜
    ECD0 煨 煅 煲 煊 煸 煺 熘 熳 熵 熨 熠 燠 燔 燧 燹 爝
    ECE0 爨 灬 焘 煦 熹 戾 戽 扃 扈 扉 礻 祀 祆 祉 祛 祜
    ECF0 祓 祚 祢 祗 祠 祯 祧 祺 禅 禊 禚 禧 禳 忑 忐
    code +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F
    EDA0 怼 恝 恚 恧 恁 恙 恣 悫 愆 愍 慝 憩 憝 懋 懑
    EDB0 戆 肀 聿 沓 泶 淼 矶 矸 砀 砉 砗 砘 砑 斫 砭 砜
    EDC0 砝 砹 砺 砻 砟 砼 砥 砬 砣 砩 硎 硭 硖 硗 砦 硐
    EDD0 硇 硌 硪 碛 碓 碚 碇 碜 碡 碣 碲 碹 碥 磔 磙 磉
    EDE0 磬 磲 礅 磴 礓 礤 礞 礴 龛 黹 黻 黼 盱 眄 眍 盹
    EDF0 眇 眈 眚 眢 眙 眭 眦 眵 眸 睐 睑 睇 睃 睚 睨
    code +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F
    EEA0 睢 睥 睿 瞍 睽 瞀 瞌 瞑 瞟 瞠 瞰 瞵 瞽 町 畀
    EEB0 畎 畋 畈 畛 畲 畹 疃 罘 罡 罟 詈 罨 罴 罱 罹 羁
    EEC0 罾 盍 盥 蠲 钅 钆 钇 钋 钊 钌 钍 钏 钐 钔 钗 钕
    EED0 钚 钛 钜 钣 钤 钫 钪 钭 钬 钯 钰 钲 钴 钶 钷 钸
    EEE0 钹 钺 钼 钽 钿 铄 铈 铉 铊 铋 铌 铍 铎 铐 铑 铒
    EEF0 铕 铖 铗 铙 铘 铛 铞 铟 铠 铢 铤 铥 铧 铨 铪
    code +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F
    EFA0 铩 铫 铮 铯 铳 铴 铵 铷 铹 铼 铽 铿 锃 锂 锆
    EFB0 锇 锉 锊 锍 锎 锏 锒 锓 锔 锕 锖 锘 锛 锝 锞 锟
    EFC0 锢 锪 锫 锩 锬 锱 锲 锴 锶 锷 锸 锼 锾 锿 镂 锵
    EFD0 镄 镅 镆 镉 镌 镎 镏 镒 镓 镔 镖 镗 镘 镙 镛 镞
    EFE0 镟 镝 镡 镢 镤 镥 镦 镧 镨 镩 镪 镫 镬 镯 镱 镲
    EFF0 镳 锺 矧 矬 雉 秕 秭 秣 秫 稆 嵇 稃 稂 稞 稔
    code +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F
    F0A0 稹 稷 穑 黏 馥 穰 皈 皎 皓 皙 皤 瓞 瓠 甬 鸠
    F0B0 鸢 鸨 鸩 鸪 鸫 鸬 鸲 鸱 鸶 鸸 鸷 鸹 鸺 鸾 鹁 鹂
    F0C0 鹄 鹆 鹇 鹈 鹉 鹋 鹌 鹎 鹑 鹕 鹗 鹚 鹛 鹜 鹞 鹣
    F0D0 鹦 鹧 鹨 鹩 鹪 鹫 鹬 鹱 鹭 鹳 疒 疔 疖 疠 疝 疬
    F0E0 疣 疳 疴 疸 痄 疱 疰 痃 痂 痖 痍 痣 痨 痦 痤 痫
    F0F0 痧 瘃 痱 痼 痿 瘐 瘀 瘅 瘌 瘗 瘊 瘥 瘘 瘕 瘙
    code +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F
    F1A0 瘛 瘼 瘢 瘠 癀 瘭 瘰 瘿 瘵 癃 瘾 瘳 癍 癞 癔
    F1B0 癜 癖 癫 癯 翊 竦 穸 穹 窀 窆 窈 窕 窦 窠 窬 窨
    F1C0 窭 窳 衤 衩 衲 衽 衿 袂 袢 裆 袷 袼 裉 裢 裎 裣
    F1D0 裥 裱 褚 裼 裨 裾 裰 褡 褙 褓 褛 褊 褴 褫 褶 襁
    F1E0 襦 襻 疋 胥 皲 皴 矜 耒 耔 耖 耜 耠 耢 耥 耦 耧
    F1F0 耩 耨 耱 耋 耵 聃 聆 聍 聒 聩 聱 覃 顸 颀 颃
    code +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F
    F2A0 颉 颌 颍 颏 颔 颚 颛 颞 颟 颡 颢 颥 颦 虍 虔
    F2B0 虬 虮 虿 虺 虼 虻 蚨 蚍 蚋 蚬 蚝 蚧 蚣 蚪 蚓 蚩
    F2C0 蚶 蛄 蚵 蛎 蚰 蚺 蚱 蚯 蛉 蛏 蚴 蛩 蛱 蛲 蛭 蛳
    F2D0 蛐 蜓 蛞 蛴 蛟 蛘 蛑 蜃 蜇 蛸 蜈 蜊 蜍 蜉 蜣 蜻
    F2E0 蜞 蜥 蜮 蜚 蜾 蝈 蜴 蜱 蜩 蜷 蜿 螂 蜢 蝽 蝾 蝻
    F2F0 蝠 蝰 蝌 蝮 螋 蝓 蝣 蝼 蝤 蝙 蝥 螓 螯 螨 蟒
    code +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F
    F3A0 蟆 螈 螅 螭 螗 螃 螫 蟥 螬 螵 螳 蟋 蟓 螽 蟑
    F3B0 蟀 蟊 蟛 蟪 蟠 蟮 蠖 蠓 蟾 蠊 蠛 蠡 蠹 蠼 缶 罂
    F3C0 罄 罅 舐 竺 竽 笈 笃 笄 笕 笊 笫 笏 筇 笸 笪 笙
    F3D0 笮 笱 笠 笥 笤 笳 笾 笞 筘 筚 筅 筵 筌 筝 筠 筮
    F3E0 筻 筢 筲 筱 箐 箦 箧 箸 箬 箝 箨 箅 箪 箜 箢 箫
    F3F0 箴 篑 篁 篌 篝 篚 篥 篦 篪 簌 篾 篼 簏 簖 簋
    code +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F
    F4A0 簟 簪 簦 簸 籁 籀 臾 舁 舂 舄 臬 衄 舡 舢 舣
    F4B0 舭 舯 舨 舫 舸 舻 舳 舴 舾 艄 艉 艋 艏 艚 艟 艨
    F4C0 衾 袅 袈 裘 裟 襞 羝 羟 羧 羯 羰 羲 籼 敉 粑 粝
    F4D0 粜 粞 粢 粲 粼 粽 糁 糇 糌 糍 糈 糅 糗 糨 艮 暨
    F4E0 羿 翎 翕 翥 翡 翦 翩 翮 翳 糸 絷 綦 綮 繇 纛 麸
    F4F0 麴 赳 趄 趔 趑 趱 赧 赭 豇 豉 酊 酐 酎 酏 酤
    code +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F
    F5A0 酢 酡 酰 酩 酯 酽 酾 酲 酴 酹 醌 醅 醐 醍 醑
    F5B0 醢 醣 醪 醭 醮 醯 醵 醴 醺 豕 鹾 趸 跫 踅 蹙 蹩
    F5C0 趵 趿 趼 趺 跄 跖 跗 跚 跞 跎 跏 跛 跆 跬 跷 跸
    F5D0 跣 跹 跻 跤 踉 跽 踔 踝 踟 踬 踮 踣 踯 踺 蹀 踹
    F5E0 踵 踽 踱 蹉 蹁 蹂 蹑 蹒 蹊 蹰 蹶 蹼 蹯 蹴 躅 躏
    F5F0 躔 躐 躜 躞 豸 貂 貊 貅 貘 貔 斛 觖 觞 觚 觜
    code +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F
    F6A0 觥 觫 觯 訾 謦 靓 雩 雳 雯 霆 霁 霈 霏 霎 霪
    F6B0 霭 霰 霾 龀 龃 龅 龆 龇 龈 龉 龊 龌 黾 鼋 鼍 隹
    F6C0 隼 隽 雎 雒 瞿 雠 銎 銮 鋈 錾 鍪 鏊 鎏 鐾 鑫 鱿
    F6D0 鲂 鲅 鲆 鲇 鲈 稣 鲋 鲎 鲐 鲑 鲒 鲔 鲕 鲚 鲛 鲞
    F6E0 鲟 鲠 鲡 鲢 鲣 鲥 鲦 鲧 鲨 鲩 鲫 鲭 鲮 鲰 鲱 鲲
    F6F0 鲳 鲴 鲵 鲶 鲷 鲺 鲻 鲼 鲽 鳄 鳅 鳆 鳇 鳊 鳋
    code +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F
    F7A0 鳌 鳍 鳎 鳏 鳐 鳓 鳔 鳕 鳗 鳘 鳙 鳜 鳝 鳟 鳢
    F7B0 靼 鞅 鞑 鞒 鞔 鞯 鞫 鞣 鞲 鞴 骱 骰 骷 鹘 骶 骺
    F7C0 骼 髁 髀 髅 髂 髋 髌 髑 魅 魃 魇 魉 魈 魍 魑 飨
    F7D0 餍 餮 饕 饔 髟 髡 髦 髯 髫 髻 髭 髹 鬈 鬏 鬓 鬟
    F7E0 鬣 麽 麾 縻 麂 麇 麈 麋 麒 鏖 麝 麟 黛 黜 黝 黠
    F7F0 黟 黢 黩 黧 黥 黪 黯 鼢 鼬 鼯 鼹 鼷 鼽 鼾 齄

    展开全文
  • unicode字符编码标准

    2011-02-22 14:47:25
    1. 编码知识 1.1 文本和字符 在计算机程序中或者数据文件里,文本(text)是作为数字序列存储的。...如何解释这些整数是由字符集(character set)、编码(encoding)决定的。 文本主要是由...
    转载自:http://blog.csdn.net/barenx/archive/2008/04/03/2246176.aspx

    1. 编码知识
    1.1 文本和字符
    在计算机程序中或者数据文件里,文本(text)是作为数字序列存储的。序列中的数字是具有不同大小、取值和解释的整数。如何解释这些整数是由字符集(character set)、编码(encoding)决定的。
    文本主要是由字符(character)组成。在格式文本(fancy text, or rich text)中包括显示属性,如颜色、斜体字、上标等,但仍然是以字符组成的纯文本(plain text)为基础的。有时,格式文本与纯文本之间的区别很复杂,依赖于具体的应用。
    什么是字符?典型地,是字母。也可以是数字、句点、连字号、标点符号和数学符号,对于中文,也可以是汉字。还包括定义行尾和段落等的控制字符(一般不可见)。
    有了字符,就可以为它们分配数字编码。为字符分配什么数字值,依赖于具体情况。一个简单的字符,如字母"a",在不同的程序或者数据文件中可能具有不同的整数值。
    1.2 字符集:具有数字编码的字符
    在信息处理中,所使用的整数总有上限,依赖于存储整数的位的数目。这也决定了可以同时区分的字符的数量。
    在设计字符集时,首先要决定所需字符的数目,并确定所需字符的清单。根据字符的数目,可以设定整数值的上限,这个整数范围称为编码空间(code space),其中的一个特定整数称为一个码点(code point)。
    然后,为字符清单中的每个字符指定一个整数值,也就是一个码点。这样就得到一个字符集,称作编码字符集(Coded Character Set)。
    1.3 编码单元、字节和编码
    在计算机系统的实现中,整数以特定大小的单元表示,通常为8位(1字节),16位,或32位。在字符编码中,这样的单元称为编码单元(code unit)。根据编码空间的大小和具体要求,来选择合适的编码单元。通常,所选择编码单元对应的整数范围要大于编码空间的整数范围,这样每个码点就只需一个编码单元表示,并且在字符码点与编码单元间的转换非常简便,因为字符码点对应的整数值与相应编码单元的整数值相同。如果编码单元对应的整数范围小于编码空间的整数范围,就需要多个编码单元表示一个码点。
    字节是计算机系统中最基本的表示单元,无论是存储在内存中,还是将文本写入文件或通过网络发送,总是要读写若干字节。因此,在实际应用中,还需要将编码单元进一步表示为字节序列。
    将字符表示为字节序列的过程就称为编码(encoding),更重要的是,还包括如何对字节序列进行解释以取得字符。
    1.4 不同的字符集
    在一些常用的编码中,每个字符只使用一个字节表示,称单字节字符集(single-byte character set, SBCS)。这些字符集都仅限于256个字符。
    在ASCII之后,目前应用最广泛的单字节字符集是ISO-8859-1。它是ASCII的一个8位超集,并且提供西欧语言所需的大多数字符。它的一个改进的版本,ISO-8859-15,还包括新的欧元符号和更多的一些法语和芬兰语字母。
    双字节字符集(double-byte character set, DBCS)用于为东亚书写系统中所使用成千上万个表意字符提供足够空间。这里的编码仍是基于字节的,不过是两个字节一起表示一个单一的字符。
    即使在东亚,文本中也会包含小字母表中的字母,如拉丁字母表。这些字母使用单字节表示的效率会更高。因此,提出了多字节字符集(multi-byte character set, MBDC),使用可变数目的字节来表示字符。多字节字符集通常与ASCII兼容,也就是说,在这种编码中,拉丁字母使用与ASCII中相同的字节来表示。一些不常用的字符可能会使用三个甚至四个字节编码。
    1.4 常见字符集
    1.4.1 ASCII: The American Standard Code form Information Interchange
    ASCII是一个使用7位单元的字符集,及针对7位字节的简单编码方式。尽管局限于很少的一些字符,ASCII是最重要的一种字符集,因为它是目前大多数字符集的基础。
    ASCII只提供了128个数字值(也可称作码点,code point),其中33个被保留用作特殊功能。只有95个码点用作"真正的"文本字符。这些图形字符大多时大写和小写拉丁字母,数字和标点符号,外加一些特殊的括号、下划线和重音符号。
    1.4.2 EBCDIC: The Extended Binary-Coded Decimal Interchange Code
    EBCDIC是由IBM设计的编码格式,使用8位字节,被一些字符集用于大型机。EBCDIC在与ASCII相近的时期开发的,具有一些相似的特性。
    1.4.3 Unicode
    Unicode标准定义了一个字符集和几种编码。
    Unicode最有吸引力的特点是它涵盖了几乎世界上的所有字符,可以只通过一个唯一的数字(Unicode码点)来访问和操作字符。
    2. Unicode介绍
    2.1 为什么使用Unicode?
    在创造Unicode之前,有数百种编码系统。但是,没有任何一个编码可以包含足够的字符。例如,仅欧州共同体就需要好几种不同的编码来包括所有的语言。即使是单一的一种语言,如英语,也没有哪一个编码可以适用于所有的字母,标点符号,和常用的技术符号。
    这些编码系统也会互相冲突。也就是说,两种编码可能使用相同的数字代表两个不同的字符,或使用不同的数字代表相同的字符。任何一台特定的计算机(特别是服务器)都需要支持许多不同的编码,但是,不论什么时候数据通过不同的编码或平台之间,那些数据总会有损坏的危险。
    而Unicode正在改变所有这一切!
    在Unicode标准中,提供了1,114,112个码点,不仅可以包含当今世界使用的所有语言文字和其他符号,也足够容纳绝大多数具有历史意义的古文字和符号。并且,Unicode给每个字符提供了一个唯一的数字,不论是什么平台,不论是什么程序,不论什么语言。
    Unicode 标准已经被工业界的领导们所采用,例如: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.2 Unicode与国际化
    直到最近,国际化的常用方法是,假定任何给定的可执行程序同时只和一种语言工作。如果在英文环境下安装,它就只处理英文文本;如果在中文环境下安装,就只处理中文文本。
    在这种模型下,针对不同的书写系统和语言,使用的字符集和字符编码不同。在Windows和大型机环境下,术语"代码页"(Code Page)用于描述如何将二进制值映射到人类可读得字符(字形)。一个运行的程序处在单一的代码页,该代码页确定二进制值如和与字形关联。
    简便的国际化是Unicode的另一项优势。在内部使用Unicode的应用程序,能够同时存储和处理世界上所有的字符,这消除了传统的国际化方法所面临的一些困难。
    当然,成功的国际化不仅仅是在应用程序中采用Unicode,还需要谨慎的屏幕布局设计(不同的语言具有不同的书写习惯)、翻译和文化理解。
    2.3 设计原则
    Unicode的设计反映了十大基本原则,但这些原则并不是可以同时满足。整个设计是在保证简便高效和保持与已有编码标准兼容之间的平衡。
    (1)广泛性(Universality)
    Unicode标准对一个单一的大字符集进行编码,包括满足世界范围需求的所有字符。
    (2)高效(Efficiency)
    在Unicode的字符编码模型中没有换码符(escape character),每个字符编码与其它字符编码具有相同的状态。使高效率的实现成为可能。
    所有Unicode编码方式都是自同步的,并且相互不重叠。使在字符流中随机访问和查找操作高效。
    同一书写字母体系中的字符被放置在一起,不仅方便字符的查找,并且使实现更紧凑压缩方法更高效。
    (3)针对字符编码,而不是字形(Character, Not Glyph)
    字符是书写语言中具有语义的最小组件的抽象表示。字符是以驻留在内存中的码点表示。
    字形是字符被显示时具有的形状。与字符相比,字形出现在屏幕或纸张上作为一个或多个字符的特定表示。字形的集合构成一种字体。
    字符和字形间存在多种关系:一个字形可以对应一个字符;一个字形也可以对应几个字符;多个字形也可能出自一个字符。
    (4)语义(Semantic)
    在Unicode中,字符都有明确定义的语义。字符属性表可用于解析、排序等需要有关码点语义知识的算法中。Unicode中定义的属性包括数字、间隔、组合和方向属性。
    (5)纯文本(Plain Text)
    纯文本或无格式文本,仅仅是字符编码的序列。纯Unicode文本就是Unicode编码的序列。而格式文本(styled text, or rich text)是由纯文本添加一些附加信息(如语言标识、字体大小、颜色等)组成的文本表示。
    Unicode标准针对的是纯文本。
    (6)逻辑顺序(Logical Order)
    Unicode文本在内存表示中以逻辑顺序存储,大致对应于借助键盘输入文本的顺序。在一些情况下,当显示或打印文本时,字符顺序与逻辑顺序不同。
    (7)统一(Unification)
    Unicode标准为避免对字符重复编码,对不同语言书写方式中的字符进行统一,相同的字符分配唯一的一个编码。普通字母、标点符号、标记,和变音符都只分配一个编码,而不管语言;同样的还有中日韩使用的表意字符。
    (8)动态组合(Dynamic Composition)
    Unicode标准允许加重音符好的形式和Hangul音节的动态组合。
    (9)等价序列(Equivalent Sequences)
    一些文本元素即可以使用静态的预先组合好的形式,也可使用动态组合的形式。Unicode字符的不同表示序列被认为是等价的。
    如果两个或多个序列被认为是等价的,Unicode标准不规定哪一种特定的序列是正确的,而认为每一个序列只不过与其它序列等价。
    如果需要一种单一的单一的表示方式,可以使用一种规范化的Unicode文本形式来减少不想要区别。Unicode标准定义了四种规范化形式: Normalization Form D (NFD),Normalization Form KD (NFKD),Normalization Form C (NFC),和Normalization Form KC (NFKC)。大约来说,NFD和NFKD将可能的字符进行分解,而NFC和NFKC将可能的字符进行组合。
    (10)可转换性(Convertibility)
    在Unicode 标准和其他字符集标准之间可以实现准确的转换。一般说,在其他标准中的一个码点对应于Unicode标准中一个单一的码点。然而,有时在其他标准中的一个码点对应于Unicode标准中一个码点的序列。在Unicode文本和其他字符编码文本间的转换一般是通过明确的表映射过程完成的。
    2.4 Unicode的码点、编码格式、编码方案
    2.4.1 Unicode编码空间和码点
    在Unicode标准中,编码空间的整数范围是从0到10FFFF(16进制),共1,114,112个可用的码点。
    为了与已有的编码标准兼容,一些抽象字符可能会与多个分别编码的字符关联。而在其他一些情况下,一个抽象字符可能会用两个(或更多)编码字符序列来表示,如带重音符的字母。
    2.4.2 Unicode编码格式
    在Unicode字符编码模型中,编码格式(encoding form)指定如何将每个码点表示为一个或多个编码单元序列。Unicode标准提供了三种不同的编码格式,使用8位、16位和32位编码单元,分别为UTF-8、UTF-16、UTF-32。
    (1)UTF-32
    UTF-32是一种最简单的Unicode编码格式。每个Unicode码点被直接表示为一个32位的编码单元。UTF-32是一种固定宽度的字符编码格式。
    每个UTF-32编码单元的值与Unicode码点的值完全相同。
    (2)UTF-16
    在UTF-16中,在范围U+0000到U+FFFF间的码点使用一个单一的16位编码单元表示;而,在范围U+10000到U+10FFFF间的码点则使用一对16位编码单元表示,称作代理对(surrogate pair)。
    UTF -16优化了基本多语言平面(Basic Multilingual Plane)中字符的表示,即位于U+0000到U+FFFF范围内的字符。该范围包含了目前世界上所使用的书写系统中的绝大多数字符,每个字符只需要一个16位的编码单元。对于基本多语言平面,UTF-16可作为固定宽度的编码格式来有效使用。
    但对于增补字符,UTF-16需要两个16位的编码单元,意味着正式的UTF-16是一个变宽的编码格式。
    UTF-16是早期Unicode遗留下的历史产物,原本被设计成具有固定宽度的16位编码格式。为支持超过U+FFFF的增补字符,设立了代理机制。
    (3)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范围的其他一些非表意字母,每个都在UTF-8种使用量各字节表示;位于U+0800到U+FFFF范围内的非代理码点使用三字节表示;超出U+FFFF的增补码点则需要四字节表示。
    UTF-8是Internet中HTML和类似协议偏好的编码格式。
    UTF-8同其他的多字节编码方式相比具有以下特点:
    a) UTF-8的编码单元序列的第一个字节指明了后面所跟的字节的数目。对前向解析非常有效。
    b) 从UTF-8字节流的任意位置开始可以有效的找到一个字符的其实位置。
    c) UTF-8中不存在字节取值的重叠。
    2.4.3 Unicode编码方案
    在Unicode标准中,用于Unicode数据字节串行化的各种不同类型的规范被称为Unicode编码方案(encoding scheme)。
    在计算机系统中,大数值类型(如整型)使用多个字节表示,不同体系结构采用的字节排列顺序不同。其中,部分采用由高字节到低字节的排列顺序,称为big-endian;其他则采用由低字节到高字节的排列顺序,称little-endian。
    对于UTF-16和UTF-32,字节串行化规范必须考虑当前表示数据的系统采用的是big-endian还是little-endian结构。
    一个字符编码方案包括指定的字符编码格式,以及如何将编码单元串行化为字节的规范。在Unicode标准中,还规定了初始的字节顺序标志(byte order mark, BOM)的使用,用于显示区分big-endian和little-endian数据。
    对于UTF-8,在序列中只包括UTF-8的编码单元(1字节),因此,UTF-8中的数据表示不存在字节顺序的问题。但对于16位和32位的编码方案,字节串行化过程必须将编码单元分解为两个或四个字节,并且必须清楚的定义这些字节的顺序。
    因此,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流或者文件,必须制定字节顺序。
    2.4.4 Unicode编码空间分配
    根据在语言学上和功能上的类别,Unicode标准中的编码字符被分成组。
    Unicode 编码空间的范围为0到10FFFF,可以被划分为字符平面(planes of characters),每个平面包含64K各码点。因此,最底层的平面为基本多语言平面(Basic Multilingual Plane),包括范围从0000到FFFF;下一个平面为增补多语言平面(Supplementary Multilingual Plane),也被称为第一平面(Plane 1),包括范围10000到1FFFF;以及,第二平面(Plane 2),增补表意字符平面(Supplementary Ideographic Plane),包括范围20000到2FFFF;等等。基本多语言平面有时也被称为Plane 0。
    基本多语言平面(BMP, or Plane 0)包含目前世界上使用的所有书写系统中的全部常用字符,以及一些历史上的不常用字符。
    增补多语言平面(SMP, or Plane 1)用于一些较少使用的历史上的书写系统,针对特殊目的创建的书写系统,和特殊的标记系统,它们要么无法放入基本多语言平面中,要么特别不常用。
    增补表意字符平面(SIP, or Plane 2)用于无法放入基本语言平面众所分配区域中/日/韩字符(CJK character)。尽管在SIP中包含少量的常用CJK字符(例如,用于粤语),其中绝大多数字符是仅具有历史意义的不常用字符。
    增补专用平面(Supplementary Special-purpose Plane, SSP, or Plane 14)用于无法放入基本多语言平面众所分配区域的格式控制字符。
    3. 一致性
    符合Unicode一致性要求的实现必须满足本部分定义的标准,以便与其他规范的实现进行交互。
    3.1 一致性要求
    3.1.1 未分配的码点(Unassigned Code Points)
    C4 处理过程不应该把高代理码点(high-surrogate code point)或者低代理码点(low-surrogate code point)解释为抽象字符。
    C5 处理过程不应该把非字符码点解释为抽象字符。
    C6 处理过程不应该将未分配的码点解释为抽象字符。
    3.1.2解释(Interpretation)
    C7 如果处理过程要解释编码字符的表示,就必须根据标准中确立的字符语义进行解释。
    C8 不要求处理过程对任何特定的编码字符都作解释。
    允许处理过程只解释Unicode字符中的一个子集;不需要解释所有Unicode字符。
    标准中不涉及任何指定字符子集的方法。
    标准中不涉及自定义区中码点的语义。
    C9 处理过程不应认为对两个具有规范等价性字符序列(canonical-equivalent character sequence)的解释会不同。
    该条款包含两层意义:(一)处理过程不应该对两个不同但又具有规范等价性的字符序列由不同的解释;(二)任何处理过程不应假设其他处理过程会对两个不同但具有规范等价性的字符序列进行不同的解释。
    3.1.3 修改(Modification)
    C10 如果一个处理过程声称不会修改对一个正确的编码字符表示的解释,则它不能对编码字符的表示进行任何修改,除非是用具有规范等价性的字符序列进行替换,或者是删除非字符的码点。
    用具有规范等价性的字符序列替换原有字符序列不会修改对文本的解释。
    替换或者删除处理过程不能会不进行解释的字符序列,不修改对文本的解释。
    当在不同计算机体系结构间转换字符序列时,对字符序列位或者字节顺序的改变,不修改对文本的解释。
    将一个正确的编码字符的表示从一种Unicode字符编码格式转换为另一种编码格式时,不修改对文本的解释。
    将编码单元序列的字节串行化从一种Unicode字符编码方案转换为另一种编码方案时,不修改对文本的解释。
    如果在处理过程中意外遇到一个没有明确内部用途的非字符,在实现中可以发出错误,或者删除或忽略该非字符。如果没有采取这些选择,这个非字符应该被作为一个为分配的码点。
    3.1.4 字符编码格式(Character Encoding Forms)
    C11 当处理过程对一个声称以某种Unicode字符编码格式存在的编码单元序列进行解释时,必须按照相应的码点序列进行解释。
    C12 当处理过程以某种Unicode字符编码格式生成编码单元序列时,不应生成形式错误(ill-formed)的编码单元序列。
    C12a 当处理过程对一个声称以某种Unicode字符编码格式存在的编码单元序列进行解释时,应该将形式错误的编码单元序列看作错误条件,而不能将序列解释为字符。
    3.1.5 字符编码方案(Character Encoding Schemes)
    C12b 当处理过程对一个具有某种Unicode字符编码方案的字节序列进行处理时,应该根据字节顺序和标准中针对字符编码方案设立的字节顺序标记(byte order mark)使用规范,进行解释。
    3.1.6 双向文本(Bidirectional Text)
    C13 用于显示包含从右到左的字符文本的处理过程,当没有高层协议时,必须以对文本应用双向算法后同样的顺序显示所有具有可见表示的字符(不包括格式字符)。
    3.1.7 正规化形式(Normalization Forms)
    C14 以某种正规化形式生成Unicode文本的处理过程,必须与Unicode Standard Annex #15 "Unicode Normalization Forms"中定义的规范相符合。
    C15 测试Unicode文本是否具有某种正规化形式的处理过程,必须与必须与Unicode Standard Annex #15中定义的规范相符合。
    C16 将文本转换为某种正规化形式的处理过程必须生成Unicode Standard Annex #15中规定的结果。
    3.1.8 标准的引用(Normative References)
    C17 对标准、属性别名、属性值别名或者Unicode算法的标准引用,必须依照Unicode标准种指定的格式。
    C18 高层协议不能对临时属性进行标准引用。
    3.1.9 Unicode算法(Unicode Algorithms)
    C19 如果处理过程声称实现某个Unicode算法,则必须符合标准中定义的算法规范,除非被高层协议改变。
    3.2 术语定义
    以下是对一致性条款中所使用术语的准确定义。
    3.2.1 字符的身份和语义(Character Identity and Semantics)
    D1 标准的行为(normative behavior):Unicode标准中的标准行为包括以下列表,以及在一致性条款种指定的其他行为。
    1. 字符组合;
    2. 规范化的分解;
    3. 兼容的分解;
    4. 规范的排序行为;
    5. 双向行为;
    6. 联合jamo行为(conjoining jamo behavior);
    7. 变化选择;
    8. 正规化。
    D2a 字符身份(character identity):一个字符的身份是由它的字符名称、表示的字形确定的。
    D2b 字符语义(character semantics):一个字符的语义是由它的身份、标准的属性和行为决定的。
    3.2.2 字符与编码(Characters and Encoding)
    D3 抽象字符(abstract character):信息的单元,用于文本数据的组织、控制或表示。
    抽象字符没有具体的形状,不应与字形混淆。
    Unicode标准中没有直接编码的抽象字符经常可以使用组合字符序列表示。
    D4 抽象字符序列:抽象字符的有序序列。
    D4a Unicode编码空间(Unicode codespace):从0到10FFFF的整数空间(十六进制)。
    D4b 码点(code point):Unicode编码空间中的任何一个整数值。
    一个码点也称为一个编码位置。
    D5 编码字符(encoded character):在一个抽象字符和一个码点间的关联。
    在Unicode中,为了与其它标准兼容,一个单个的抽象字符可能与多个码点对应。
    一个单个的抽象字符也可能使用一个码点序列表示。
    D6 编码字符表示(coded character representation):一个码点序列。通常,是由编码字符的序列组成,但也可能包含非字符或保留的码点。
    编码字符表示也称为编码字符序列(coded character sequence)。
    在内部,处理过程可能会在编码字符表示中使用非字符码点。但是,这些非字符码点可能不会被解释成抽象字符;并且,如果这些非字符码点被具有一致性的处理过程删除,不构成对编码字符表示解释的修改。
    D7a 不赞成使用的字符(deprecated character):强烈不鼓励使用的编码字符。
    在标准中保留不赞成使用的字符,以便使以前相容的数据仍然与今后的Unicode标准保持一致性。
    D7b 非字符(noncharacter):被永久保留做内部使用的码点,不应用于交换。非字符包括值U+nFFFE和U+nFFFF(n表示十六进制整数从0到10),以及值从U+FDD0到U+FDEF。
    D7c 保留的码点(reserved code point):Unicode标准中保留的,用于今后分配的码点。也称为位分配码点(unassigned code point)。
    代理码点和非字符码点是已分配的码点,但不是分配给字符。
    D8 高层协议(higher-level protocol):任何超出Unicode标准范围,对Unicode字符进行解释协议。
    D8a Unicode算法(Unicode Algorithm):对处理过程的逻辑描述,用于获得涉及Unicode字符的指定结果。
    3.2.3 属性(Properties)
    (1)标准的和指示性属性(Normative and Informative Properties)
    Unicode字符属性可以分为标准的和指示性的。
    D9 标准属性(normative property):Unicode字符属性,它的取值必须为与标准相一致。
    D9a 指示性属性(Informative property):Unicode字符属性,它的取值仅仅是为了提供更多信息。
    D9b 临时的属性(provisional property):Unicode字符属性,它的取值未被批准、试验性的,也可能是不完全的。
    (2)简单的和衍生出的属性(Simple and Derived Properties)
    D9c 简单属性(simple property):Unicode字符属性,它的取值在UCD,the Unicode Character Database(或标准中的其他地方)直接指定,并且它的取值无法从其他简单属性中衍生出来。
    D9d 衍生属性(derived property):Unicode字符属性,它的取值可通过算法从一些简单属性的组合中衍生出来。
    (3)属性别名(Property Aliases)
    D10 属性别名(property alias):特定Unicode字符属性的一个唯一标示名。
    用于属性别名的标示名中仅包含ASCII中的字母、数字和下划线。
    为每个属性别名分别定义了长、短两种形式的名称。短的形式一般只有两个或三个字符长,便于在标记语言中用于标记属性。
    D10a 属性值别名(property value alias):为Unicode字符属性的特定取值定义的唯一标示名。
    用于属性值别名的标示名中仅包含ASCII中的字母、数字和下划线,或者是特殊的值"n/a"。
    为每个属性值别名分别定义了长、短两种形式的名称。
    属性值别名仅在相关联的特定属性环境中唯一。
    (4)却省属性值(Default Property Value)
    D11 却省属性值(default property value):针对一个给定的Unicode属性,用于指派给未分配的码点或没有明确指定其他属性值的属性值。
    (5)私用(Private Use)
    D12 私用码点(private-use code point):在范围U+E000到U+F8FF、U+F0000到U+FFFFD和U+100000到U+10FFFD内的码点。
    私用码点被认为已分配给字符,但标准中没有指定对私用码点相关联的抽象字符的解释。
    私用码点可能会被赋予却省的属性值,但这些却省值可以被对私用码点进行解释的高层协议替换。
    3.2.4 组合(Combination)
    D13 基字符(base character):在书写上,不与前面的字符进行组合的字符,它既不是控制字符也不是格式字符。
    D14 组合字符(combining character):在书写上,与前面的基字符进行组合的字符。称组合字符应用于基字符。
    组合字符不单独使用。它们包括重音符、变音符、希伯莱文中的点、阿拉伯文元音符号等。
    尽管组合字符用来与基字符组合显示的,但可能出现两种情况(1)在组合字符前没有基字符;(2)处理过程无法执行组合操作。在这两种情况下,处理过程可能会不进行书写上的合并而显示组合字符。
    在编码表中,组合字符的表示使用虚线圆圈描绘。当与前面的基字符组合显示时,基字符要出现在虚线圆圈的位置上。
    组合字符一般具有它们的基字符的属性,同时保留它们的组合属性。
    控制字符和格式字符,如tab和right-left mark不是基字符。
    D15 非间距标记(nonspacing mark):在显示时,位置取决于基字符的组合字符。这些字符一般在可视基线上不占用空间。
    这些字符可能会很大,影响它们的基字符相对于前后基字符的放置。
    D16 间距标记(spacing mark):不是非间距标记的组合字符。
    一般来说,间距标记的行为与基字符没有太大区别。
    D17 组合字符序列(combining character sequence):一个字符序列,由一个基字符后跟了一个或多个组合字符组成,或者是一个或多个组合字符的组成的序列。
    D17a 不良的组合字符序列(defective combining character sequence):一个不是以基字符开始的组合字符序列。
    当组合字符序列出现在串的开始位置,或者跟在控制字符或格式字符后出现时,产生不良的组合字符序列。
    3.2.5 分解(Decomposition)
    D18 可分解字符(decomposable character):根据分解映像表,与一个或多个字符组成的序列等价的字符。也被称作预组合字符(precomposed character)或复合字符(composite character)。
    D19 分解(decomposition):与一个可分解字符等价的一个或多个字符组成的序列。一个字符序列的完全分解,是对序列中每个字符进行分解直到没有字符可以进一步分解。
    (1)兼容的分解(Compatibility Decomposition)
    D20 兼容的分解(compatibility decomposition):递归应用Character Names List中的兼容映像表和规范映像表,以及Conjoining Jamo Behavior中的定义,对字符进行分解,直到没有任何字符可以进一步分解,并根据Canonical Ordering Behavior中的定义对非间距标记进行重新排序。
    D21 兼容的可分解字符(compatibility decomposable character):兼容分解的结果与规范分解结果不相同的字符。
    (2)规范的分解(Canonical Decomposition)
    D23 规范的分解(canonical decomposition):递归应用Character Names List中的规范映像表,以及Conjoining Jamo Behavior中的定义,对字符进行分解,直到没有任何字符可以进一步分解,并根据Canonical Ordering Behavior中的定义对非间距标记进行重新排序。
    D21 规范的可分解字符(compatibility decomposable character):与规范分解结果不相同的字符。
    D24 规范等价性(canonical equivalent):如果两个字符序列的完全规范分解结果相同,称它们具有规范的等价性。
    3.2.6 代理(Surrogates)
    D25 高代理码点(high-surrogate code point):位于范围U+D800到U+DBFF内的Unicode码点。
    D25a 高代理编码单元(high-surrogate code unit):在范围D800到DBFF内的16位编码单元,作为UTF-16中代理对的起始编码单元。
    D26 低代理码点(low-surrogate code point):位于范围U+DC00到U+DFFF内的Unicode码点。
    D26a 低代理编码单元(low-surrogate code unit):在范围DC00到DFFF内的16位编码单元,作为UTF-16中代理对的结尾编码单元。
    D27 代理对(surrogate pair):由两个16位编码单元组成的序列来表示单个的抽象字符,其中,代理对的第一部分为高代理编码单元,第二部分为低代理编码单元。
    代理对仅用于UTF-16。
    孤立的代理编码单元自身没有解释。
    3.2.7 Unicode编码格式(Unicode Encoding Forms)
    D28 Unicode标量值(Unicode scalar value):除了高代理和低代理码点外的其他所有Unicode码点。
    D28a 编码单元(code unit):为了处理和交换,表示编码文本单元的最小的位组合。
    编码单元是计算机存储中的特定单元。Unicode标准在UTF-8中使用8位编码单元,在UTF-16中使用16位编码单元,在UTF-32中使用32位编码单元。
    在Unicode标准中,一些编码单元的特定值不能单独用于表示编码字符。该限制条件应用于UTF-16中孤立的代理码点,以及UTF-8中的字节80-FF。
    D28b 编码单元序列(code unit sequence):一个或多个编码单元的有序序列。
    当编码单元是8位时,编码单元序列也可被称作字节序列。
    一个编码单元序列可能只有一个单个的编码单元。
    在程序设计语言中,字符串类型的值基本由编码单元序列组成。
    依赖字符编码标准的结构,可能要使用编码单元序列(包含多个编码单元)来表示一个单个的编码字符。
    D29 Unicode编码格式将每个Unicode标量值分配给一个唯一的编码单元序列。
    由于历史原因,Unicode编码格式也被称作Unicode(or UCS) transformation formats(UTF)。
    在Unicode标量值集合与针对Unicode编码格式的编码序列集合间的映射是一对一的。
    对给定的编码格式,存在编码单元序列没有相关联的Unicode标量值。
    D29a Unicode串(Unicode string):由Unicode编码格式中编码单元组成的编码单元序列。
    D29b 8位Unicode串(Unicode 8-bit string):只包含UTF-8编码单元的Unicode串。
    D29c 16位Unicode串(Unicode 16-bit string):只包含UTF-16编码单元的Unicode串。
    D29d 32位Unicode串(Unicode 32-bit string):只包含UTF-32编码单元的Unicode串。
    D30 形式不良的(ill-formed):如果具有Unicode编码格式的Unicode编码单元序列没有遵照Unicode编码格式规范,就称为形式不良的。
    如果编码单元序列对应的码点位与Unicode标量范围之外,就是形式不良的。
    UTF-8对起始字节和后续字节的字节范围有严格的约束。违反这些约束,将使生成的编码单元序列无法映射到Unicode标量值上,产生一个形式不良的编码单元序列。
    D30a 形式良好的(well-formed):遵照Unicode编码格式规范的Unicode编码单元序列,就成为形式良好的。
    D30b 形式良好的UTF-8编码单元序列(well-formed UTF-8 code unit sequence)
    D30c 形式良好的UTF-16编码单元序列(well-formed UTF-16 code unit sequence)
    D30d 形式良好的UTF-32编码单元序列(well-formed UTF-32 code unit sequence)
    D30e 具有Unicode编码格式(in a Unicode encoding form):如果一个Unicode串是由某个特定的Unicode编码格式的形式良好的编码单元序列组成,称该Unicode字符串具有Unicode编码格式。
    UTF-32
    D31 UTF-32编码格式(UTF-32 encoding form):一种Unicode编码格式,为每个Unicode标量值分配一个单一的无符号的32位编码单元,编码单元的数字值与Unicode标量值相同。
    因为代理码点没有包括在Unicode标量值集合中,所以位与范围0000D800到0000DFFF间的UTF-32编码单元使形式不良的。
    任何大于0010FFFF的UTF-32编码单元是形式不良的。
    UTF-16
    D35 UTF-16编码格式(UTF-16 encoding form):一种Unicode编码格式,为处在范围U_0000到U+D7FF和U+E000到U+FFFF内的每个Unicode标量值分配一个单一的无符号的16位编码单元,编码单元的数字值与Unicode标量值相同;位处在范围U+10000到U+10FFFF内的每个Unicode标量值分配一个代理对。
    因为代理码点不是Unicode标量值,位于范围D800到DFFF间单独的UTF-16编码单元是形式不良的。
    UTF-16 Bit Distribution
    Scalar Value UTF-16
    xxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxx
    000uuuuuxxxxxxxxxxxxxxxx 110110wwwwxxxxxx110111xxxxxxxxxx
    wwww=uuuuu-1
    UTF-8
    D36 UTF-8编码格式(UTF-8 encoding form):一种Unicode编码格式,位每个Unicode标量值分配一个由一到四个无符号字节组成的序列。
    UTF-8 Bit Distribution
    Scalar Value 1st Byte 2nd Byte 3rd Byte 4th Byte
    00000000 0xxxxxxx 0xxxxxxx
    00000yyy yyxxxxxx 110yyyyy 10xxxxxx
    zzzzyyyy yyxxxxxx 1110zzzz 10yyyyyy 10xxxxxx
    000uuuuu zzzzyyyy yyxxxxxx 11110uuu 10uuzzzz 10yyyyyy 10xxxxxx
    编码格式转换(Encoding Form Conversion)
    D37 编码格式转换:在一种Unicode编码格式的编码单元序列与另一种Unicode编码格式的编码单元序列间,直接定义的转换。
    * 在Unicode标准实现中,一个典型的API在逻辑上,将输入的编码单元序列转化为Unicode标量值(码点),然后将标量值转化为输出的编码单元序列。然而,可以直接在不同编码格式间进行转换,以获取更高的效率。
    * 具有一致性的编码格式转换过程应将任何形式不良的编码单元序列作为一个错误条件。
    3.2.8 Unicode编码方案(Unicode Encoding Schemes)
    D38 Unicode编码方案:针对Unicode编码格式的一种指定的字节串行换,也可包括处理字节顺序标记(byte order mark, BOM)的规范。
    D39 UTF-8编码方案(UTF-8 encoding scheme):对UTF-8编码单元序列进行串行化的Unicode编码方案,字节序列与编码单元序列本身完全一致。
    D40 UTF-16BE编码方案(UTF-16BE encoding scheme):将UTF-16编码单元序列串行化为big-endian格式字节序列的Unicode编码方案。
    D41 UTF-16LE编码方案(UTF-16LE encoding scheme):将UTF-16编码单元序列串行化为little-endian格式字节序列的Unicode编码方案。
    D42 UTF-16编码方案(UTF-16 encoding scheme):将UTF-16编码单元序列串行化为big-endian或者little-endian格式字节序列的Unicode编码方案。
    在UTF-16编码方案中,与U+FEFF对应的初始字节序列,被解释为字节顺序标记(BOM),用于区分两种字节顺序。初始字节顺序<FE FF>表明是big-endian顺序,<FF FE>表明是little-endian顺序。BOM不是文本内容的一部分。
    UTF-16编码方案可能以BOM开始,也可能没有。然而,如果没有BOM,也没有高层协议指示,UTF-16编码方案的字节顺序为big-endian。
    D43 UTF-32BE编码方案(UTF-32BE encoding scheme):将UTF-32编码单元序列串行化为big-endian格式字节序列的Unicode编码方案。
    D44 UTF-32LE编码方案(UTF-16LE encoding scheme):将UTF-32编码单元序列串行化为little-endian格式字节序列的Unicode编码方案。
    D45 UTF-32编码方案(UTF-32 encoding scheme):将UTF-32编码单元序列串行化为big-endian或者little-endian格式字节序列的Unicode编码方案。
    在UTF-32编码方案中,与U+FEFF对应的初始字节序列,被解释为字节顺序标记(BOM),用于区分两种字节顺序。初始字节顺序<00 00 FE FF>表明是big-endian顺序,<FF FE 00 00>表明是little-endian顺序。BOM不是文本内容的一部分。
    UTF-32编码方案可能以BOM开始,也可能没有。然而,如果没有BOM,也没有高层协议指示,UTF-16编码方案的字节顺序为big-endian。
    3.2.9规范排序行为(Canonical Ordering Behavior)
    用于对组合字符序列提供无歧义的解释,以便能按照可预知的方式创建和交换包含组合字符的序列。正规化是规范排序行为的另一个重要应用。
    在Unicode标准中,组合字符序列中字符的顺序按照以下原则解释:
    所有组合字符必须跟在所应用的基字符后面。
    封闭的标记(enclosing mark)将包围基字符以及标记之前的所有组合字符。也包围它之前的其他封闭标记。
    double diacritic的结合程度比其他非间距标记(nonspacing mark)要松。当显示时,double diacritic的位置在其他变音符之上,不包括封闭的变音符。
    具有相同组合类别(combining class)的组合标记在书写上的位置一般是由所修饰的基字符向外排列。一些特定的非间距标记将改变却省的排列行为,与相邻的非间距标记并行排列。当并行排列时,编码的顺序与书写中占支配的顺序有关。
    如果组合字符的组合类别不同,将不会有显示形式或语义上的差别。
    (1)组合类别(Combining Class)
    D46 组合类别:分配给每个Unicode组合字符的数字值,用于确定与那些组合字符在排字上相互作用。
    如果组合字符间在排字上相互作用,则具有相同的组合类别;否则,具有不同类别。
    封闭字符和间距组合字符的组合类别与它们的基字符相同。
    组合类别具有的特定数字没有特别的重要性,只是用来比较是否相等,区分不同的组合类别。
    (2)规范排序(Canonical Ordering)
    对一个被分解的字符序列的规范排序,是根据组合类别对每个组合字符序列进行排序来完成的。字符序列的规范排序不反映任何语言正确性或偏好。
    对被分解的字符序列D进行规范排序的算法为:
    R1 对D中的任意字符x,定义p(x)为字符x的组合类别。
    R2 如果在D中存在想的字符对(A,B),并且p(B)不为零,p(A)>p(B),则交换两个字符。
    R3 重复执行R2,直到在D中没有发生任何交换。
    (3)Conjoining Jamo Behavior
    在Unicode标准中包含了一套预组合的Hangual音节,以及一套用于表示古老的韩文音节和现代韩文音节的jamo。
    4. 实现指南
    4.1 编码转换(Transcoding to Other Standards)
    一般,在Unicode标准和其他编码标准间的映射需要通过表(table)来完成,而不是算法转换。使用表查找常常具有比简单算法转换更高的效率。
    (1)多级表(Multistage Tables)
    转换表需要空间。即使是很小的字符集也经常会映射到Unicode标准中几个不同的区块中,因此,至少在一个转换方向上(从Unicode标准到其他编码标准或相反),可能会包含多至64K个项(针对BMP)或1,088K个项(针对全部编码空间)。有多个方法用于减少映射表的内存空间需求,这些方法不仅可用于转换表,也可用于其他实现Unicode标准的表结构,包括字符属性数据、case映射等等。
    (2)Flat Tables
    如果磁盘空间不是问题,虚拟内存体系可以为flat table安排可接受大小的工作集,因为各字符的使用频率有很大不同,即使是小字符集也包含一些不常使用的字符。并且,需要转换为给定字符集的数据中的字符一般不会来自Unicode标准中的所有区块。
    (3)Ranges
    提供一个精心创建的嵌套范围判断对表进行优化,可能比较吸引人。但由于分支损失,这种方法会对现代的高度流水线式的处理器体系造成不必要的性能耗费。一种快速的解决方案是采用优化的两级表,可以在编码中不包含任何测试或分支指令。尽管哈希表的速度不如多级表,但也可用于空间优化。
    (4)两级表(Two-Stage Tables)
    两级表示常用的一种减少表的大小的机制。两级表使用一个指针和却省值的数组。如果指针为空NULL,查找返回却省值。否则,指针指向用于第二级查找的数值块。对于BMP字符,按照高字节和低字节值来组织这样的两级表非常有效,第一级是由256个指针组成数组,每个第二集区块中包含256个值。对于增补字符,应采取不同的方法构造指针和二级数组,以便充分考虑增补字符在剩余编码空间中稀疏的散布。
    (5)优化的两级表(Optimized Two-Stage Table)
    当任何区块相同时,对应的指针只需其中一个区块。对编码转换表而言,这种情况一般出现在当区块中的字符仅仅映射到"却省"或"无法匹配"的字符时。不是使用空指针NULL和一个却省值,而是创建了一个却省项的"共享"块。由于避免使用测试和分支,这种策略可以提供接近于简单数租访问的速度,却大大节省了存储空间。
    (6)多级表调节(Multistage Table Tuning)
    给定一个具有任意大小和内容的表,可以较容易的创建一个小的应用程序,来计算多级表的最佳级数和它们的宽度。通过调节级数和它们的索引指针数组的宽度,可以在表大小和平均访问时间之间进行折衷。
    4.2 ANSI/ISO C wchar_t
    在ANSI/ISO C中,为固定宽度的宽字符定义了类型wchar_t,ANSI/ISO C将宽字符集语义的定义留给了特定的实现。
    wchar_t的宽度是由编译器指明的,可以只有8位大小。因此,需要在不同C或C++编译器间可移植的程序不应该使用wchar_t存储Unicode文本。
    对于UTF-16的实现,可以使用宏macro或者类型定义typedef(如UNICHAR),编译为unsigned short或者wchar_t(依赖于目标编译器和平台)。对UTF-32的实现可以使用编译为unsigned int或wchar_t的宏或者是类型定义。这样的选择使在不同的系统平台和编译其中可以正确编译。
    4.3 未知和缺少的字符(Unknown and Missing Characters)
    4.3.1 保留的和私用的字符编码(Reserved and Private-Use Character Codes)
    有两类码点,即使是完全的Unicode标准实现也无法正确解释:
    被保留的码点;
    在私用区中的码点。
    一个实现不应试图去解释这样的码点。然而,在实际中,应用程序必须处理为分配的码点或私用字符。例如,当应用程序所处理的文本是由一个实现更新版本的Unicode标准的系统创建的,其中包含更多的分配字符。
    对未知字符显示的选择包括将码点显示为四到六位十六进制数字,显示一个黑得或白的方块,针对保留字符和私用字符分别显示适合的字形,或者什么都不显示。一个实现不能删除这样的字符,也不能无目的地转换为其他字符。
    4.3.2可解释但无法显示的字符(Interpretable but Unrenderable Character)
    一个实现可能接收一个分配给Unicode字符的码点,但无法显示它,因为没有字体或者无法正确显示。
    在这种情况下,实现可能会对用户的询问提供进一步有限的反馈,如对数据进行适当的排序,显示它的书写系统,或者以却省放时显示码点。对无法显示的(但是已分配的)码点和未分配的码点,实现可以通过为无法显示的码点使用指示类别的不同字形表示。
    4.3.3却省的属性值(Default Property Value)
    要使实现可以正常工作,需要把未分配的码点看作字符分配却省的属性值,因为各种算法都需要分配给每个码点的属性值来运作。这些却省值不是对所有未分配的码点都相同,因为码点中的某些范围需要不同的属性值以便与将来期望的分配做到最大兼容。
    除非被特指,却省属性值不是标准的,具有一致性的实现可以使用其他值。例如,取代却省值,实现可能使用以下规则,为一块未分配字符插入相邻已分配字符的属性值。
    注意在两个方向上最接近的已分配字符,如果它们处在相同的块中具有相同的属性值,则使用这些值。
    从任一区块的边界开始,一直扩展到块内最近的已分配字符处为止,使用区块中字符对应的属性值。
    如果所有的码点完全位于空的或未分配的块中,使用对应属性的却省值。
    4.3.4却省的可忽略的码点(Default Ignorable Code Points)
    一般,在可支持字符集外的码点使用一个应变的字形显示,如一个黑方块。然而,格式和控制字符不应该由可见的字形(尽管它们对其他字符的显示有影响)。除非对于一些特定的处理,这些字符也被忽略,例如,字符ZERO WIDTH NON-JOINER在对照(collation)中忽略。为在不同版本的标准间保证最大程度的兼容性,范围U+2060到U+206F,U+FFF0到 U+FFFB,和U+E0000到U+E0FFF保留给格式和控制字符。在这些范围中的位分配码点应该在处理和显示中被忽略。
    4.4 处理UTF-16中的代理对(Handling Surrogate Pairs in UTF-16)
    在形式良好的UTF-16中,在一个低代理码点之前只能是一个高代理码点,而不能是另一个低代理码点、一个非代理码点或者是文本的开头。一个高代理码点的后面也只能跟一个低代理码点,而不能是另一个高代理码点、一个非代理码点或者是文本的结尾。
    高代理码点和低代理码点被分配了不相交的编码单元,非代理的码点也不会使用这些范围内的编码单元值表示。因此,在形式良好的UTF-16中的每个编码单元必须只满足下面三个可能的条件之一:
    一个单一的非代理编码单元表示的码点范围是0到D7FF或E000到FFFF;
    一个高代理码点表示代理对的第一部分;
    一个低代理码点表示代理对的第二部分。
    最多访问两个编码单元,使用UTF-16编码格式的处理过程就可以解释任何Unicode字符。确定字符边界最多只需要扫描前一个或后一个编码单元,而不需考虑其他部分。
    只要实现不去除代理对中的任一编码单元,或者在代理对中两个编码单元间错误的插入另一个字符,就可以保证数据的完整性。而且,即便数据被破坏了,错误也是局部的。
    UTF-16具有非常有利的频率分布,在所有文本数据中的大多数部分中,代理对非常罕见,非代理码点将非常普遍。这不仅有利于减少由于处理变长编码而带来的性能损失,也允许一些处理过程可以不对代理对采取特别的操作,或者使用已有处理字符序列的机制来处理代理对。
    实现必须在处理UTF-16文本时完全支持代理对。但是,实现中的单独的组件可以具有对代理对不同程度的支持,只要这些组件之间可以正确的组合和交流。对代理对不同程度的支持由两个主要方面决定:
    实现是否解释增补的字符?
    实现是否保证代理对的完整性?
    Surrogate Support Levels
    Support Level Interpretation Interity of Pairs
    None No supplementary characters Does not guarantee
    Transparent No supplementary characters Guarantees
    Weak Some supplementary characters Does not guarantee
    Strong Some supplementary characters Guarantees
    不支持代理对,实现就不会对任何增补字符进行解释,也不保证代理对的完整性。
    透明的代理对支持(transparent surrogate support),用于这样的组件,如编码格式转换,它可能完全保证对代理对的正确处理,但不解释任何增补字符。也适用于低层串处理操作的组件,一个 Unicode串只是简单地作为编码单元的数组而不顾它们的代理状态,不对串进行解释。
    不充分的代理支持(weak surrogate support)只正确地处理那些对应可解释字符的代理对,可能调用的组件被保证不会传递无法解释的字符。
    支持代理对的策略(Strategies for Surrogate Pair Support)
    处理Unicode标准中高级特性的一些实现可以很容易地被改进,来支持UTF-16的代理对。例如:
    在文本对照(text collation)中可以把代理对作为"组合字符"来处理。
    文本的输入可以使用一次按键产生两个Unicode码点的键盘来完成,就如一次ENTRE键可以生成CRLF或者在阿拉伯键盘上的"lam-alef"可以生成两个字符lam和alef的序列。
    文本截断(truncation)可以使用与保证组合标记紧跟基字符相同的机制。
    如果文本编辑器可以保证插入点(insertion point)位于字符边界,就可以阻止用户破坏文本。只要使用文本元素边界,低层的串处理程序(如wcschr)就不用进行修改。实际上,只有某些高层的处理需要注意代理对;底层的例程可以继续使用对16位编码单元操作,而不需特别对待代理对。
    4.5 处理数字(Handling Number)
    在Unicode 中,有一些字符集合用于表示不同书写系统中的十进制数字。在数字上,解释这些字符的系统必须提供正确的数字值。比如,在数字上,对序列<U+ 0968 DEVANAGARI DIGIT TWO, U+0966 DEVANAGARI DIGIT ZERO>解释,具有值20。
    当从二进制的数字值转换为可视的形式时,可以从不同的书写系统中选择数字。
    ASCII数字的全角变形(fullwidth)仅是通常数字的兼容变形,应作为一般的西文数字对待。
    罗马数字和东亚的表意字符数字也是十进制的数字书写体系,但它们在形式上不是以10为基数的数字系统。因此,不可能采用一对一的方式转换成像123456.789的形式。
    使用表意字符,也可能以两种方法书写数字。如数字1,234可以表示为"一千二百三十四"或"一二三四"。在数字解析使支持这些数字意味着实现必须能区分这两种情况。
    有时候数字需要解析,但它们并不是数的一部分。例如由字母和数字组成的标示符。
    只有在另一层上(如实现一个完整的数学公式解析器),对上标(superscripting)的解释才是至关重要的。
    4.6 正规化(Normalization)
    (1)可选择的拼写(Alternative Spelling)
    在Unicode标准中对最常用的一些加重音符的字符分配明确的编码。这些字符也可以通过组合获得,对于加重音符的字母,可以由基字符和非间距标记(nonspacing mark)组合而来。
    Unicode标准提供对可由基字符加一个或多个非间距标记组合而来字符的分解。分解映射与特定Unicode标准的版本有关。
    (2)正规化(Normalization)
    系统可能会将Unicode编码格式的文本正规化为特定的序列,如将组合字符序列正规化为由预组合字符的序列,或者相反。
    无法处理非间距标记的系统,可以正规化为预组合字符,适用于大多数基于拉丁语的现代语言。对于无法处理的组合字符,系统可以使用替代显示方法,至少在显示上表示组合。
    对可以处理非间距标记的系统,执行正规化消除预组合字符可能会有用,使系统对组合字符有统一的表示,保持对这类字符处理的一致性。
    4.7 压缩(Compression)
    使用Unicode字符编码可能会增加用于保存文件文本部分的存储和内存空间。因此,对Unicode文件或串进行压缩是一个很好的选择。压缩往往建立一个更高层的协议,并且依赖于所使用的压缩方法的知识进行交换。
    4.8 换行的原则(Newline Guidelines)
    换行符在不同的平台上表示为:carriage return(CR)、line feed(LF)、CRLF,或next line(NEL)。不仅换行符使用不同的字符表示,并且在相同平台上,它们也具有不明确的行为。当转换字符集编码时,这些字符通常被直接转换为对应的 Unicode码点。这意味着,即使是处理纯Unicode文本的程序也必须解决这些问题。特别是随着Web的出现,在一台机子上的文本可能具有不同的来源,将引起很大问题。
    换行符用来明确指示行的边界。
    4.8.1 定义(Definitions)
    Hex Values for Acronyms
    Acronym Name Unicode ASCII
    CR carriage return 000D 0D
    LF line feed 000A 0A
    CRLF carriage return and line feed 000D,000A 0D,0A
    NEL next line 0085 85
    VT vertical tab 000B 0B
    FF form feed 000C 0C
    LS line separator 2028 n/a
    PS paragraph separator 2029 n/a
    在Unicode标准中,没有正式地分配控制字符,而是为各种7位和8位字符编码标准中使用控制字符提供相应的码点。确保了Unicode标准与其他编码标准的相关性和相互映射。
    缩写NLF(newline function)表示针对一个新行分隔符的一般控制功能。
    4.8.2 背景(Background)
    段落分隔符(paragraph separator)用于指示段落之间的分隔。行分隔符(line separator)指示在何处进行断行,特别是在一个段落中。
    记录分隔符(record separator)用于分隔记录。例如,当交换表格式数据时,一种普通的格式是使用TAB分隔单元和在一行单元后使用CRLF。尽管这种功能与行分隔不是正好相同,但使用了同样的字符。
    NLF开始时作为行分隔符。现在,在一些简单的文本编辑器中还作为行的分隔符。随着平台和程序开始使用自动分行进行字处理,这些字符被用于表示段落分隔符。
    一旦NLF被用来表示段落分隔符,在一些情况下,另一个控制字符就被作为行分隔符使用。例如,在Microsoft Word中,就使用vertical tabulation(VT)。
    4.8.3 建议(Recommendation)
    在Unicode 中,定义了两个明确的分隔字符:U+2029 PARAGRAPH SEPARATOR(PS)和U+2028 LINE SEPARATOR(LS)。在Unicode文本中,应该在所表达功能明确的地方使用PS和LS字符。否则,当从其他字符集转换为Unicode时,当解释文本中的字符时,和当从Unicode转换为其他字符集时,使用以下规则处理NLF。
    即使实现知道在一个特定的平台上用哪个字符表示NLF,在输入和解释时CR、LF、CRLF和NEL应该被相同对待。只要在输出时,才有必要进行区分。
    (1)从其他字符编码集转换
    R1 如果知道NLF的确切的用法,则转换为LS或PS。
    R1a 如果不知道NLF的确切用法,则映射为与平台对应的NFL。
    (2)解释文本中的字符
    R2 总把PS解释为段落间隔,把LS解释为行间隔。
    R2a 在字处理中,把任一NLF都解释为PS。
    R2b 在简单文本编辑中,把任一NLF都解释为LS。
    R2c 在解析中选择最安全的解释。
    例如,对R2c,涉及断句启发规则的实现会按照以下方法,将NLF安全的解释为LS:
    当一个NLF应是PS时,假设把它解释为LS。因为多数段落总是以标点符号结束,这只会在个别情况造成对句子边界的错误识别。
    当一个NLF应是LS时,假设把它解释为PS。在这种情况下,行分隔符将是句子断开,对断句启发规则带来很大错误。
    (3)转换为其他字符编码集
    R3 如果已知转换的目标,根据目标协定,适当地对NLF、LS和PS进行映射。
    例如,当映射为Microsoft Word对文档的内部协定时,LS将映射为VT,PS和其他NLF将映射为CRLF。
    R3a 如果不知道转换的目标,将NLF、LS和PS映射到平台的换行协定。
    (4)输入和输出
    R4 函数readline应该在遇到NLF、LS、FF或PS时停止。在典型的实现中,不包括停止位置的NLF、LS、FF或PS。
    因为分隔符会丢失,对这种readline函数的使用仅限于与分隔符的类型无关的文本处理。
    R4a 函数writeline应该根据(3)中的协议转换NLF、LS和PS。
    (5)页面分隔符
    FF一般用作页面分隔符,在文本中应该按照情况解释。当在屏幕上显示时,在分隔符后的文本会被强制放如下一页。它与段落分隔符无关:一个段落可以在一页开始在下一页中继续。除非是在页面中显示,在大多数解析过程和readline中,与LS的解释相同。
    4.9 正则表达式(Regular Expressions)
    面向字节的正则表达式工具需要扩展以正确处理Unicode。下面是扩展所涉及方面:
    Unicode是一个很大的字符集,只适用于处理小字符集的正则表达式工具可能无法调整。
    Unicode包括多种语言,它们具有与英语或其他西欧语言非常不同特性。
    4.10 纯文本中的语言信息(Language Information in Plain Text)
    4.10.1 语言标记的需要
    在纯文本数据中嵌入语言信息的需要经常被夸大。一些普通操作,如对照(collation)很少需要这些额外信息。
    然而,语言信息对某些操作非常有用,如对一个混合语言的文档执行拼写检查或者连字(hyphenating)。对于为无格式文本选择却省字体也非常有用,例如日文字体中的省略符号具有与英文字体不同的外观。当前的字体和布局(layout)技术基于语言信息产生不同结果。尽管语言信息对于执行文本-语音转换 (text-to-speech)操作有用,但当前的文本-语音转换软件都必须对文本执行非常复杂的语法分析,因此确定语言的额外工作就不那么重要了。
    语言信息可以使用带外信息(out-of-band)或内嵌标记(inline tag)表示。在内部实现中,通常使用带外信息,保存在与文本并联的数据结构中,而不是嵌入到文本数据中。带外信息不影响对文本的正常处理,还可以轻松的支持对文本的操作。
    4.10.2 语言标记与汉字统一
    对Unicode中汉字统一的一个常见误解是觉得没有语言信息就无法正确显示汉字字符。其实,汉字统一的目标和方法是确保文本可读。尽管需要添加字体、大小、宽度和其他格式规格,以便在源和目标机器上准确产生相同的外观,但在没有这些规格时,纯文本也能保证可读。
    因为不同国家所使用的统一的汉字间的不同,都仅限于格式上的变化,不会引起Unicode中的混乱。在Unicode中的汉字统一不会使读者音唯一不同的字体显示而无法识别一个字符。如果准确的字体信息很重要,最好使用格式文本。
    4.11 编辑和选择(Editing and Selection)
    一致的文本元素(Consistent Text Elements)
    从用户的角度,文本的基本表示不是所关心的,但重要的是,编辑接口必须对用户所认为的字符提供一个统一的实现。用户希望在鼠标选择、方向键移动、退格等操作中,这些字符表现得像一个个单元。例如,当实现这些行为后,对一个表示为基字符加非间距组合标记序列的加重音符字母,使用右移方向键时,逻辑上会从基字符的开始跳到最后一个非间距字符后面。
    在词中的编辑和选择,一般有三种类型的边界(boundary)。
    簇边界(cluster boundary)
    任意定义的簇边界可能会出现在像梵文(Devanagari)这样的书写系统中,选择操作可能会应用于音节或者音节的一部分。在这种情况下,组合字符序列,如ka+vowel sign或者联合的簇ka+halant+ta,作为单一的单元选择。
    堆叠字符边界(stacked boundary)
    堆叠字符边界一般比簇边界更细。独立的元素(如梵文vowel sign a)可以不受约束的选择,但是任何堆叠在一起的字符(包括垂直连字符,如阿拉伯文中的lam+meem)只能作为单一的单元选择。
    原子字符边界(atomic character boundary)
    原子字符边界的使用最接近于单个Unicode字符的选择。然而,大多数当前系统都采用某种矩形加亮的方式表示选择操作。这种方法限制了编辑操作的一致性,因为一些字符序列不是从行的起始处成直线地发展。当字符堆叠时,两种机制被用于对部分选择地显示:直线的和非直线的边界。
    直线的边界(linear boundary)
    使用直线边界,将合成字形的全部宽度都归属于序列的第一个字符,认为其余字符没有宽度。
    这是最简单的一种机制。它的优点是只需要很少的额外实现工作。它的缺点是选择窄字符变得非常困难,更不用说零宽度的字符。需要用户刚好从非间距标记右边开始选择,并且正好拖到左边。如果有多个非间距标记,它也不允许对单个标记进行选择。
    非直线的边界(nonlinear boundary)
    使用非直线边界把任何堆叠字符分成各个部分。可以通过对多个矩形加亮,或者对单个字符着色的方法进行表示。
    注意到,通过更多的操作,一个预组合的字符在删除操作中可以表现得像一个具有原子字符边界组合字符序列一样。这个过程包括动态地获得字符的分解表示,得到用作模拟的组件。
    在多数系统中,字符时文本中最小的可寻址单元,所以选择操作和属性分配操作(如字体、颜色、字符间距等)都在字符的基础上执行。对于预组合地字符无法模拟这种可寻址性,系统地修改所有文本编辑工具来对字符的一部分进行寻址,会十分低效。
    由于文本元素不具有一个单一的概念,因此,对字符边界的编辑也没有一个统一的概念。在不同情况下,用户可能会在编
    展开全文
  • 如何解释这些整数是由字符集(character set)、编码(encoding)决定的。 文本主要是由字符(character)组成。在格式文本(fancy text, or richtext)中包括显示属性,如颜色、斜体字、上标等,
  • Unicode 1. 编码知识 ...如何解释这些整数是由字符集(character set)、编码(encoding)决定的。 文本主要是由字符(character)组成。在格式文本(fancy text, or rich text)中包括显示属性,如颜...
  • python字符编码

    2017-11-16 16:03:00
    最早的字符编码标准:ASCII 127个字符,没有中文 1个英文字母需要1个字节 8个位=1字节 1024字节=1kb 1024kb=1MB 后来为了扩展中文支持,出现了GB2312、GBK后来出现Unicode 把所有语言统一到一套编码里 每个字符占...
  • 字符编码

    2018-12-23 23:24:37
    字符编码 编码 按历史 ASCII 最早的编码表,1个字节,后7位表示编码。将字符编成一张码表。比如0x0D表示回车 多字节编码 因为ASCII只能表示127个字符,当涉及到多种语言时,就不够了。所以出现了多字节编码的字符集...
  • 在计算机上使用的最常见的字符集或字符编码是ASCII美国信息交换标准代码,这可能是电子编码文本中使用最广泛的字符集。ASCII编码仅支持大写和小写的拉丁字母,数字0-9和一些额外的字符,共计128个字符。您可以查看...
  • 字符集 1.ASCII ...字符编码转换方法 1.使用C++标准库codecvt、locale、use_facet https://zh.cppreference.com/w/cpp/locale/codecvt https://zh.cppreference.com/w/cpp/locale/use_facet h.
  • 常见字符编码

    2010-11-24 10:18:00
    由于历史原因,出现了多种字符编码标准,这些标准所使用的字符集和编码映射关系是大不相同的,有的标准效率高,但覆盖的字符(支持的抽象字符)太少,而有的支持大量字符,但由于编码格式的局限,效率较低。...
  • 计算机要准确的处理各种字符集文字,需要进行字符编码及相应的解码,以便计算机能够识别和存储各种文字。简单介绍一下,只为下一篇文章引出Unicode字符编码。 ASCII字符集 ASCII(American Standard Code for ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 8,167
精华内容 3,266
关键字:

字符编码标准