Unicode详解
字符编码的问题,每个程序员都会遇到,深入探索其背后的原理和机制,能让我们少走很多弯路。 Unicode ( 万国码 、 国际码 、 统一码 、 单一码 )是计算机科学领域里的一项业界标准。它对世界上大部分的文字系统进行了整理、编码,使得电脑可以用更为简单的方式来呈现和处理文字。 Unicode发展由非营利机构统一码联盟负责,该机构致力于让Unicode方案替换既有的字符编码方案。因为既有的方案往往空间非常有限,亦不适用于多语环境。 统一码联盟在1991年首次发布了 The Unicode Standard 。 在2005年,Unicode的第十万个字元被引入成为标准之一,该字元被用于马拉雅拉姆语。 目前实际应用的统一码版本对应于UCS-2,使用16位的编码空间。也就是每个字符占用2个字节。这样理论上一共最多可以表示2的16次(即65536)个字符。基本满足各种语言的使用。实际上当前版本的统一码并未完全使用这16位编码,而是保留了大量空间以作为特殊使用或将来扩展。 最新(但未实际广泛使用)的统一码版本定义了16个辅助平面,两者合起来至少需要占据21位的编码空间,比3字节略少。但事实上辅助平面字符仍然占用4字节编码空间,与UCS-4保持一致。未来版本会涵盖UCS-4的所有字符。UCS-4是一个更大的尚未填充完全的31位字符集,加上恒为0的首位,共需占据32位,即4字节。理论上最多能表示2的31次方个字符,完全可以涵盖一切语言所用的符号。 通用字符集 (Universal Character Set)是由ISO制定的 ISO 10646 (或称 ISO/IEC 10646 )标准所定义的标准字符集。 通用字符集包括了其他所有字符集。它保证了与其他字符集的双向兼容,即,如果你将任何文本字符串翻译到UCS格式,然后再翻译回原编码,你不会丢失任何信息。 UCS包含了已知语言的所有字符。除了拉丁语、希腊语、斯拉夫语、希伯来语、阿拉伯语、亚美尼亚语、格鲁吉亚语,还包括中文、日文、韩文这样的方块文字,UCS还包括大量的图形、印刷、数学、科学符号。 ISO/IEC 10646定义了一个31位的字符集。 并不是所有的系统都需要支持像组合字符这样的的先进机制。因此ISO 10646指定了如下三种实现级别: 历史上存在两个独立的尝试创立单一字符集的组织,即: 1、国际标准化组织(ISO)于1984年创建的ISO/IEC 2、统一码联盟 统一码联盟和ISO/IEC都同意保持两者标准的码表兼容,并紧密地共同调整任何未来的扩展。 Unicode的实现方式不同于编码方式。一个字符的Unicode编码是确定的。但是在实际传输过程中,由于不同系统平台的设计不一定一致,以及出于节省空间的目的,对Unicode编码的实现方式有所不同。 Unicode的实现方式称为 Unicode转换格式 (Unicode Transformation Format,简称为 UTF )。 前面说到,Unicode采用2个字节来编码文件,但是如果一个仅包含7位ASCII字符的Unicode文件,每个字符使用2字节就浪费了一般的存储空间,其第一字节的8位始终为0,这是难以忍受。对于这种情况,可以使用UTF-8编码,这是一种变长编码,它将基本7位ASCII字符仍用7位编码表示,占用一个字节(首位补0)。而遇到与其他Unicode字符混合的情况,将按一定算法转换,每个字符使用1-3个字节编码,并利用首位为0或1进行识别。 问题来了,UTF-8变长编码格式的出现是为了节省存储空间,变长导致了UTF-8的兼容性相应降低。 类似的,对未来会出现的需要4个字节的辅助平面字符和其他UCS-4扩充字符,2字节编码的UTF-16也需要通过一定的算法进行转换。 也就是说,UTF-16是为未来准备的变长编码格式。 还有就是,在Mac和普通PC上,对于字节顺序的理解是不一致的。这时同一字节流可能会被解释为不同内容,如某字符为十六进制编码4E59,按两个字节拆分为4E和59,在Mac上读取时是从低字节开始,那么在Mac OS会认为此4E59编码为594E,找到的字符为“奎”,而在Windows上从高字节开始读取,则编码为U+4E59的字符为“乙”。就是说在Windows下以UTF-16编码保存一个字符“乙”,在Mac OS环境下打开会显示成“奎”。此类情况说明UTF-16的编码顺序若不加以人为定义就可能发生混淆。 于是在UTF-16编码实现方式中使用了 大端序 (Big-Endian,简写为UTF-16 BE)、 小端序 (Little-Endian,简写为UTF-16 LE)的概念,以及可附加的字节顺序记号解决方案,目前在PC机上的Windows系统和Linux系统对于UTF-16编码默认使用UTF-16 LE。目前在PC机上的Windows系统和Linux系统对于UTF-16编码默认使用UTF-16 LE。 在Windows XP附带的记事本,“另存为”对话框可以选择的四种编码方式除去非Unicode编码的ANSI(对于英文系统即ASCII编码),中文系统则为GB2312或Big5外,其余三种为“Unicode”(对应UTF-16 LE)、“Unicode big endian”(对应UTF-16 BE)和“UTF-8”。 UTF-8,是我们最经常看到的编码格式之一。前面已经简单介绍过,这是一种变长编码格式,变长的目的是节省存储空间。 UTF-8使用一至六个字节为每个字符编码(2003年11月UTF-8被RFC 3629重新规范,只能使用原来Unicode定义的区域,U+0000到U+10FFFF,也就是说最多四个字节)。 下面介绍其编码规则: 1、128个US-ASCII字符只需一个字节编码(Unicode范围由U+0000至U+007F)。 2、带有附加符号的拉丁文、希腊文、西里尔字母、亚美尼亚语、希伯来文、阿拉伯文等则需要两个字节编码(Unicode范围由U+0080至U+07FF)。 3、其他基本多文种平面(BMP)中的字元(这包含了大部分常用字,如大部分的汉字)使用三个字节编码(Unicode范围由U+0800至U+FFFF)。 4、其他极少使用的Unicode 辅助平面的字元使用四至六字节编码。(Unicode范围由U+10000至U+1FFFFF使用四字节,Unicode范围由U+200000至U+3FFFFFF使用五字节,Unicode范围由U+4000000至U+7FFFFFFF使用六字节)。 对上述提及的第四种字元而言,UTF-8使用四至六个字节来编码似乎太耗费资源了。但UTF-8对所有常用的字元都可以用三个字节表示,而且它的另一种选择,UTF-16编码,对前述的第四种字符同样需要四个字节来编码,所以要决定UTF-8或UTF-16哪种编码比较有效率,还要视所使用的字元的分布范围而定。 下面来看看UTF-8具体怎么编码各种类型的字符: 1、单字节编码,字节由零开始:0zzzzzzz。(z取值0或1,下同) 2、两字节编码:(110yyyyy 10zzzzzz)第一个字节由110开始,接着的字节由10开始 3、三字节编码:(01110xxxx10yyyyyy 10zzzzzz)第一个字节由1110开始,接着的字节由10开始。 4、四字节编码:(11110www 10xxxxxx 10yyyyyy 10zzzzzz)将由11110开始,接着的字节由10开始 UTF-16 是Unicode字符编码五层次模型的第三层:字符编码表。即把Unicode字符集的抽象码位映射为16位长的整数,用于数据存储或传递。Unicode字符的码位,需要1个或者2个16位长的码元来表示,因此这是一个变长表示。 Unicode的编码空间从U+0000到+10FFFF,共有1,112,064个码位(code point)可用来映射字符. Unicode的编码空间可以划分为17个平面(plane),每个平面包含216(65,536)个码位。17个平面的码位可表示为从U+xx0000到U+xxFFFF,其中xx表示十六进制值从0016到1016,共计17个平面。第一个平面称为 基本多语言平面 (Basic Multilingual Plane, BMP ),或称第零平面(Plane 0)。其他平面称为 辅助平面 (Supplementary Planes)。基本多语言平面内,从U+D800到U+DFFF之间的码位区段是永久保留不映射到Unicode字符。UTF-16就利用保留下来的0xD800-0xDFFF区段的码位来对辅助平面的字符的码位进行编码。 分平面来介绍UTF-16的实现方式: 1、第一个Unicode平面(码位从U+0000至U+FFFF)包含了最常用的字符。该平面被称为基本多语言平面,缩写为 BMP (Basic Multilingual Plane, BMP)。UTF-16与 UCS-2 编码这个范围内的码位为16比特长的单个码元,数值等价于对应的码位. BMP中的这些码位是仅有的可以在UCS-2中表示的码位. 2、辅助平面(Supplementary Planes)中的码位,在UTF-16中被编码为 一对 16比特长的码元(即32bit,4Bytes),称作 代理对 (surrogate pair),具体方法是: 算法可理解为:辅助平面中的码位从U+10000到U+10FFFF,共计FFFFF个,即220 =1,048,576个,需要20位来表示。如果用两个16位长的整数组成的序列来表示,第一个整数(称为前导代理)要容纳上述20位的前10位,第二个整数(称为后尾代理)容纳上述20位的后10位。还要能根据16位整数的值直接判明属于前导整数代理的值的范围(210=1024),还是后尾整数代理的值的范围(也是210 =1024)。因此,需要在基本多语言平面中保留不对应于Unicode字符的2048个码位,就足以容纳前导代理与后尾代理所需要的编码空间。这对于基本多语言平面总计65536个码位来说,仅占3.125%. 3、Unicode标准规定U+D800..U+DFFF的值不对应于任何字符. 参考资料: https://zh.wikipedia.org/wiki/Unicode https://zh.wikipedia.org/wiki/UTF-8 https://zh.wikipedia.org/wiki/UTF-16
常用Unicode编码
unicode编码范围: 汉字:[0x4e00,0x9fa5](或十进制[19968,40869]) 数字:[0x30,0x39](或十进制[48, 57]) 小写字母:[0x61,0x7a](或十进制[97, 122]) 大写字母:[0x41,0x5a](或十进制[65, 90]) 汉字编码范围:\u4E00-\u9FA5 双字节字符编码范围:\u0391-\uFFE5 双字节字符编码范围 汉字unicode编码表 一般使用2w基本汉字就够了 | 字符集 | 字数 | Unicode 编码 | | 基本汉字 | 20902字 | 4E00-9FA5 | | 基本汉字补充 | 38字 | 9FA6-9FCB | | 扩展A | 6582字 | 3400-4DB5 | | 扩展B | 42711字 | 20000-2A6D6 | | 扩展C | 4149字 | 2A700-2B734 | | 扩展D | 222字 | 2B740-2B81D | | 康熙部首 | 214字 | 2F00-2FD5 | | 部首扩展 | 115字 | 2E80-2EF3 | | 兼容汉字 | 477字 | F900-FAD9 | | 兼容扩展 | 542字 | 2F800-2FA1D | | PUA(GBK)部件 | 81字 | E815-E86F | | 部件扩展 | 452字 | E400-E5E8 | | PUA增补 | 207字 | E600-E6CF | | 汉字笔画 | 36字 | 31C0-31E3 | | 汉字结构 | 12字 | 2FF0-2FFB | | 汉语注音 | 22字 | 3105-3120 | | 注音扩展 | 22字 | 31A0-31BA | | 〇 | 1字 | 3007 |
unicode编码是什么?
Unicode是一种字符编码方案,它为每种语言中的每个字符都设定了统一唯一的二进制编码,以实现跨语言、跨平台进行文本转换、处理的要求。Unicode是国际组织制定的可以容纳世界上所有文字和符号的字符编码方案。目前的Unicode字符分为17组编排,0x0000至0x10FFFF,每组称为平面(Plane),而每平面拥有65536个码位,共1114112个。主要内容为了使Unicode与已存在和广泛使用的旧有编码互相兼容,尤其是差不多所有电脑系统都支援的基本拉丁字母部分,所以Unicode的首256字符仍旧保留给ISO8859-1所定义的字符,使既有的西欧语系文字的转换不需特别考量。另方面因相同的原因,Unicode把大量相同的字符重复编到不同的字符码中去,使得旧有纷杂的编码方式得以和Unicode编码间互相直接转换,而不会遗失任何资讯。举例来说,全角格式区段包含了主要的拉丁字母的全角格式,在中文、日文、以及韩文字形当中,这些字符以全角的方式来呈现,而不以常见的半角形式显示,这对竖排文字和等宽排列文字有重要作用。
unicode编码是什么?
Unicode是一种字符编码方案,它为每种语言中的每个字符都设定了统一唯一的二进制编码,以实现跨语言、跨平台进行文本转换、处理的要求。Unicode是国际组织制定的可以容纳世界上所有文字和符号的字符编码方案。目前的Unicode字符分为17组编排,0x0000至0x10FFFF,每组称为平面(Plane),而每平面拥有65536个码位,共1114112个。Unicode 编码表BMP SMP SIP SSP0000—0FFF 8000—8FFF 10000—10FFF 20000—20FFF 28000—28FFF E0000—E0FFF1000—1FFF 9000—9FFF 21000—21FFF 29000—29FFF2000—2FFF A000—AFFF 12000—12FFF 22000—22FFF 2A000—2AFFF3000—3FFF B000—BFFF 23000—23FFF4000—4FFF C000—CFFF 24000—24FFF 2F000—2FFFF5000—5FFF D000—DFFF 1D000—1DFFF 25000—25FFF6000—6FFF E000—EFFF 26000—26FFF7000—7FFF F000—FFFF 1F000—1FFFF 27000—27FFF
utf-8编码
utf-8意思是编码格式为UTF-8格式。编码是用预先规定的方法将文字、数字或其它对象编成数码,或将信息、数据转换成规定的电脉冲信号。为保证编码的正确性,编码要规范化、标准化,即需有标准的编码格式。常见的编码格式有ASCII、ANSI、GBK、GB2312、UTF-8、GB18030和UNICODE等。UTF-8是针对Unicode的一种可变长度字符编码。可以用来表示Unicode标准中的任何字符,而且其编码中的第一个字节仍与ASCII相容,使得原来处理ASCII字符的软件无须或只进行少部分修改后,便可继续使用。因此逐渐成为电子邮件、网页及其他存储或传送文字的应用中,优先采用的编码。基本特征:UCS字符U+0000到U+007F(ASCII)被编码为字节0×00到0x7F(ASCIⅡ兼容)。这意味着只包含7位ASCIl字符的文件在ASCIⅡ和UTF-8两种编码方式下是一样的。UTF-8编码字符理论上可以最多到4个字节长,然而16位BMP字符最多只用到3字节长,Bigendian UCS-4字节串的排列顺序是预定的,字节0xFE和OxFF在UTF-8编码中从未用到。
Unicode编码和UTF-8编码解析
根据该文 Unicode编码和UTF-8编码的关系 粗略的写了个思维导图,并摘抄了一部分内容。 UTF-8编码把一个Unicode字符根据不同的数字大我码成1-6个字节,常用的英文字母被编码成1个字节,汉字通常是3个字节,只有很生僻的字符才会被编码成4-6个字节。如果你要传输的文本包含大量英文字符,用UTF-8编码就能节省空间: ( UTF 是英文 Unicode Transformation Format 的缩写,意为把 Unicode 字符转换为某种格式。UTF 系列编码方案(UTF-8、UTF-16、UTF-32)均是由 Unicode 编码方案衍变而来,以适应不同的数据存储或传递,它们都可以完全表示 Unicode 标准中的所有字符。目前,这些衍变方案中 UTF-8 被广泛使用,而 UTF-16 和 UTF-32 则很少被使用。) 从上面的表格还可以发现,UTF-8编码有一个额外的好处,就是ASCII编码实际上可以被看成是UTF-8编码的一部分,所以,大量只支持ASCII编码的历史遗留软件可以在UTF-8编码下继续工作。 在计算机内存中,统一使用Unicode编码,当需要保存到硬盘或者需要传输的时候,就转换为UTF-8编码。
unicode8.0 共多少字符集
我们一般通常使用的字符集有:ASCII ISO-8859-1 GB2312 big5 GBK Unicode2.0,另外还有一种基于32位的GB18030字符集是国家新出来的一种字符集,其为一个汉字设计了4个字节,因此可以说是目前为止,对汉字支持无论是简体还是繁体都是支持比较好的一种,当然主要的缺点就是太占空间,不利于在网路上传输。
如果不考虑GB18030字符集的话,最详尽的字符集应该是Unicode了,差不多支持了GBK所支持的所有汉字不敢过总量上还是稍微差一点。GBK尽管不是国家标准,但是已经成为事实上的一个行业标准,同时支持汉字的简体和繁体两种字体。比Gig5和GB2312强大些,为了更加明确的说明各个字符间的差异,先详细说明如下:
ASCII:
7位字符集,包括52个大小写英语字母,10个阿拉伯数字,1个空格,32个符号。
适用于纯英文环境,兼容性最好,在其他各种字符集下都能正确识别;不适用于英语以外的环境。
Latin1(ISO-8859-1):8位字符集,向下兼容ASCII字符集,并增加了一些西欧语言中的字母和符号。
优点:适用于西欧语种,得到世界广泛的软件支持;
缺点:不能表示拉丁语系以外的语言,不兼容少量只使用7位字符集的古老程序。
GB2312:16位字符集,收录有6763个简体汉字,682个符号;
优点:适用于简体中文环境,属于中国国家标准,在大陆(和新加坡?)得到广泛支持;
缺点:不兼容繁体中文,其汉字集合过少。
big5:16位字符集,收录有13060个繁体汉字,440个符号;
优点:适用于繁体中文环境,属于台湾官方标准,为繁体Windows所使用,在台湾和香港得到广泛支持,而且,由于台湾软件业发展较早,国外软件支持big5的比支持gb2312/gbk的要多;
缺点: 不兼容简体中文环境,和gb2312之间需要转换。
GBK:16位字符集,收录有21003个汉字,883个符号;
优点:适用于简繁中文共存的环境,为简体Windows所使用(代码页cp936),向下完全兼容gb2312;
缺点:不属于官方标准,和big5之间需要转换。
GB18030:32位字符集;收录汉字数不详,应该相当详尽。
优点:可以收录所有你能想到的文字和符号,属于中国最新的国家标准;
缺点:由于空间使用效率低(一个汉字占四个字节),运行速度慢, 目前支持它的软件较少。
Unicode2.0: 16位字符集(ucs2),收录有汉字20902个,符号6811个;
优点:适用于国际化环境,可以做为字符的内部表示和存储形式,来实现软件的国际化、本地化;
缺点:目前支持较少,与其他中文字符集不兼容。
使用哪一种字符集,需要根据使用环境而定。不要盲目的使用最大最全的字符集,这样不仅运行效率差,占用多余空间,而且会降低软件的兼容性,因为不是所有运行环境都安装有所有字符集。
如果只处理英文,则可以使用Latin1字符集,目前绝大多数机子上都可以支持。如果只处理简体中文,使用GB2312,如果同时需要支持简繁体中文,使用 GBK;如果确实需要使用偏僻字,再使用GB18030;GB2312/BIG5/GBK/GB18030都只适用于中文环境,如果需要国际化,当然要使用unicode。
有人说,同时存在和使用这么多字符集,会人为的增加软件的开发难度和不兼容性。我也认同这一点,但是,目前多种字符集的存在,尤其是多种中文字符集并存,有其现实的背景和应用,不能简单的要求使用某一个字符集就完事,否则只是不切实际的空想。GBK的编码位利用率高,汉字覆盖面广,支持简繁体同时显示,并且广泛应用于简体中文Windows环境中,已近乎成为事实上的标准,得到了越来越广泛的国际支持,但它不是国家标准。最新的GB18030是典型的学院派标准,要用一个大而全的字符集来替代现有的GB2312、GBK等,却没有考虑到实际应用的可能性。且不说其在一般应用中造成的双倍的存储空间浪费和传输带宽浪费(虽然目前单位存储价格急遽下降,不需要在象过去那样计较,但也不表示我们可以任意挥霍),更重要的是其实现的高度复杂性和编码查找及转换时的低效率,这在系统软件当中是不可容忍的。
其实,任何一种字符集都不可能适用于所有环境,字符集的设计应该根据不同的需要来分别设计,在尽量避免重复功能的字符集的同时,保持字符集之间尽可能的兼容性。更好的中文字符集的实现应该是实现两种国家标准,一种16位字符集,一种32位字符集。16位字符集用于一般性应用,类似于目前的GBK(或者直接把GBK做为标准)。32位字符集向下兼容16位字符集(或直接采用Unicode 3.0),用于文字处理等场合。操作系统和数据库管理系统等系统性软件需要同时支持这两种字符集,而一般的应用软件只需要选择一种适合自己的就行了。
字符编码的Unicode
如上ANSI编码条例中所述,世界上存在着多种编码方式,在ANSi编码下,同一个编码值,在不同的编码体系里代表着不同的字。在简体中文系统下,ANSI 编码代表 GB2312 编码,在日文操作系统下,ANSI 编码代表 JIS 编码,可能最终显示的是中文,也可能显示的是日文。在ANSI编码体系下,要想打开一个文本文件,不但要知道它的编码方式,还要安装有对应编码表,否则就可能无法读取或出现乱码。为什么电子邮件和网页都经常会出现乱码,就是因为信息的提供者可能是日文的ANSI编码体系和信息的读取者可能是中文的编码体系,他们对同一个二进制编码值进行显示,采用了不同的编码,导致乱码。这个问题促使了unicode码的诞生。如果有一种编码,将世界上所有的符号都纳入其中,无论是英文、日文、还是中文等,大家都使用这个编码表,就不会出现编码不匹配现象。每个符号对应一个唯一的编码,乱码问题就不存在了。这就是Unicode编码。Unicode当然是一个很大的集合,现在的规模可以容纳100多万个符号。每个符号的编码都不一样,比如,U+0639表示阿拉伯字母Ain,U+0041表示英语的大写字母A,“汉”这个字的Unicode编码是U+6C49。Unicode固然统一了编码方式,但是它的效率不高,比如UCS-4(Unicode的标准之一)规定用4个字节存储一个符号,那么每个英文字母前都必然有三个字节是0,这对存储和传输来说都很耗资源。