unicode编码的认识

 

1.初识unicode和ucs

1.1 unicode,翻译为统一码、万国码、单一码、标准万国码,是计算机科学领域里的一项业界标准。它对世界上大部分的文字系统进行了整理、编码,使得电脑可以用更为简化地方式来呈现和处理文字。Unicode依随着通用字符集的标准而发展,同时也以书本的形式对外发表。[来自wiki].

unicode标准经历了多次修改,至今还在修改,相信未来还会修改下去,目前版本是6.2,参见www.unicode.org.

1.2 通用字符集(Universal Character Set,UCS)是由ISO制定的ISO 10646(或称ISO/IEC 10646)标准所定义的标准字符集。通用字符集又称Universal Multiple-Octet Coded Character Set,中国大陆译为通用多八位编码字符集,台湾译为广用多八位元编码字元集。通用字符集是所有包括了其他字符集。它保证了与其他字符集的双向兼容,即,如果你将任何文本字符串翻译到UCS格式,然后再翻译回原编码,你不会丢失任何信息。UCS包含了已知语言的所有字符。除了拉丁语、希腊语、斯拉夫语、希伯来语、阿拉伯语、亚美尼亚语、格鲁吉亚语,还包括中文、日文、韩文这样的方塊文字,UCS还包括大量的图形、印刷、数学、科学符号。ISO/IEC 10646定义了一个31位的字符集。[来自wiki].

1.3 两者的关系,unicode和ucs由两个不同的机构维护,都尝试创立单一字符集的组织,即国际标准化组织(ISO)和多语言软件制造商组成的統一碼聯盟。前者开发的 ISO/IEC 10646 项目,后者开发的統一碼项目。因此最初制定了不同的标准。1991年前后,两个项目的参与者都认识到,世界不需要两个不兼容的字符集。于是,它们开始合并双方的工作成果,并为创立一个单一编码表而协同工作。从Unicode 2.0开始,Unicode采用了与ISO 10646-1相同的字库和字码;ISO也承诺,ISO 10646将不会替超出U+10FFFF的UCS-4编码赋值,以使得两者保持一致。[来自wiki].

2. unicode的理解

2.1 unicode编码在计算机领域已经变的越来越常规化,也被大多数人所熟识,操作系统,数据库,xml,java都以unicode或者其他表达方式(比如,utf-8)作为其标准字符,或者支持unicode。或许有人认为没有和unicode有过亲密接触,而事实上他接触过utf-8,utf-16, 而无论是utf-8还是utf-16都是Unicode转换格式(Unicode Transformation Format)中的一种,unicode转换格式除了上述两种还包括utf-32,utf-7. unicode目前所表达的字符范围是0x0000-0x10ffff, 以后可能还会更大。事实上unicode是使用一个4字节的int型数字试图表达出人类所能掌控的所有语言的字符,想象一下,unicode其实就是定义了一张二维表,这个二维表包含两个字段,一个是字符编码值(或者成为序号),另一个是已经收录的人类掌控的字符,每一个字符所对应的编码值就称之为这个字符的unicode编码值。从目前unicode的表达范围来看,它只用了int型的低21位,高11位还空闲,所有高11位目前来说都是0. 

2.2 很多初学者认识unicode都存在一个误区,就是unicode可以使用一个short类型表示,从unicode的字符范围来看,这是错误的,unicode需要用int表示,这个int值就是码位(codepoint).

2.3 Unicode的码空间从U+0000到U+10FFFF,共有1,112,064个码位(code point)可用来映射字符. Unicode的码空间可以划分为17个平面(plane),每个平面包含216(65,536)个码位。每个平面的码位可表示为从U+xx0000到U+xxFFFF, 其中xx表示十六进制值从0016 到1016,共计17个平面。第一个平面成为基本多文种平面(Basic Multilingual Plane, BMP),或稱第零平面(Plane 0)。其他平面称为辅助平面(Supplementary Planes)。基本多语言平面內,從U+D800到U+DFFF之間的码位區段是永久保留不映射到字符,因此UTF-16利用保留下来的0xD800-0xDFFF区段的码位來對輔助平面的字符的码位進行編碼. [来自wiki]

2.4 unicode的编码值是一定的,但每一个码值需要占用4个字节,但大英文环境的字符只需要一个字节就足够了,那么在存储或者传输时就存在巨大空间浪费,因此人们开发处理上述提到unicode格式转换技术

2.4.1 utf-16,从U+0000至U+D7FF以及从U+E000至U+FFFF的码位,16bit正好能表示对应的码位的字符,该平面被称为基本多语言平面,缩写为BMP;从U+10000到U+10FFFF的码位

辅助平面(Supplementary Planes)中的码位,在UTF-16中被编码为一对16比特长的码元(即32bit,4Bytes),称作 code units called a 代理对(surrogate pair),有时也翻译成增补字符对,需要使用两个short表示一个字符,具体方法是(来自wiki):

1)码位减去0x10000, 得到的值的范围为20比特长的0..0xFFFFF.

2)高位的10比特的值(值的范围为0..0x3FF)被加上0xD800得到第一个码元或称作高位代理(high surrogate), 值的范围是0xD800..0xDBFF. 由于高位代理比低位代理的值要小,所以为了避免混淆使用,Unicode标准现在称高位代理为前导代理(lead surrogates).

3)低位的10比特的值(值的范围也是0..0x3FF)被加上0xDC00得到第二个码元或称作低位代理(low surrogate), 现在值的范围是0xDC00..0xDFFF. 由于低位代理比高位代理的值要大,所以为了避免混淆使用,Unicode标准现在称低位代理为后尾代理(trail surrogates).

 

由于utf-16至少使用两个字节表示一个字符,在计算机内部表示一个多字节的数时根据cpu所支持的不同其内部存储也不同,比如在x86体系中,数值的高位在内存中存储在地址的高位,比如0xfeff, 地址0x000001 存储 0xff,那么0x000002存储0xfe,这称之为小端(littleEndian),反之称之为大端(bigEndian), 早期的Macintosh苹果机就是大端。所以在做utf-16转换时,系统不同转换的结果就不同,为了各个系统的统一有时需要明确支持需要的是大端还是小端,utf-16le和utf-16be分别对应这两种情况。使用大小端约定可以解决一部分问题,但有时候也会引起混乱,所以支持大小端自描述的utf-16格式出现,utf-16通过在文件开头放置一个bom字符表来描述其大小端,bom, byte order maker, 其值是0xfeff,如果bom是fffe,则对应小端,反之大端。

2.4.2 utf-8,变长编码,unicode字符可以表示位1-4个字节,如果unicode字符码位在ascii范围内,那他只占一个字符,[0x80 ,0x7FF]占连个字符,[0x800 ,0xFFFF]占3个字符,[0x10000,0x10FFFF] 占4个字符。每一范围的第一个字节有前导表示位,表示这个codepoint占几个字节,后面的每一个字节的前两位都是10.[wiki里有详细的算法]。一般来讲,utf-8编码是自描述的,他能描述一个码位占几个字节,其基础存储单元是字节,他应该是不需要bom的,但在微软平台上会画蛇添足,会产生一个bom,oxefbbbf,它应该是0xfeff的utf-8编码(没有验证过),使用windows ue或者linux vim,hexdump可以查看到bom。

2.5,GBK,GB2312与unicode的关系,他们没有关系,各自有各自的编码值,unicode比前面两个收录更多的字符,GBK完全兼容GB2312,同一个字符在GBK和unicode的编码空间内编码值不同,但他们指向同一个字符,故可以相互转换。

 

3. java与unicode

java全面支持unicode,java中的string是采用utf-16编码的,即一个字符最少需要16位来描述,Character类基于unicode4.0标准(jdk1.6),Character类的文档中含有对unicode的知识的一些描述,这个类也提供一些静态方法用户codepoint与char数组的相互转换。Charset类描述了各种字符集,他采用了提供者模式,可以动态的注册新的字符集支持,java规范规定下面都字符集必须支持:

US-ASCII 7 位 ASCII 字符,也叫作 ISO646-US、Unicode 字符集的基本拉丁块 

ISO-8859-1   ISO 拉丁字母表 No.1,也叫作 ISO-LATIN-1 

UTF-8 8 位 UCS 转换格式 

UTF-16BE 16 位 UCS 转换格式,Big Endian(最低地址存放高位字节)字节顺序 

UTF-16LE 16 位 UCS 转换格式,Little-endian(最高地址存放低位字节)字节顺序 

UTF-16 16 位 UCS 转换格式,字节顺序由可选的字节顺序标记来标识 

 

java支持utf-8编码,其中对文件的操作,支持标注的UTF-8,但DataInput接口采用的是utf-8变种。http://docs.oracle.com/javase/7/docs/api/java/io/DataInput.html#modified-utf-8.

 

String.getBytes(Charset),提供的各种字符集之间的转换。

 

4. c++,java

java字符串常量以utf-16表示

c++(windows下),缺省依赖与编译机器的本地系统编码,如果是gbk,那么内部存储格式就是gbk,如果使用L宏,就是utf-16

c++与java间数据通讯需要注意约定一致的编码,约定大端或者小端,或者使用自描述

 

 

参考文献:

1.java se文档,String,Character,Charset

2. http://zh.wikipedia.org/wiki/Unicode%E5%AD%97%E7%AC%A6%E5%88%97%E8%A1%A8

3. http://zh.wikipedia.org/wiki/%E9%80%9A%E7%94%A8%E5%AD%97%E7%AC%A6%E9%9B%86

4. http://zh.wikipedia.org/zh-cn/Unicode#XML.E5.92.8CUnicode

5. http://zh.wikipedia.org/wiki/UTF-16

6. http://zh.wikipedia.org/wiki/UTF-8


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值