注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

中吴南顾惟一笑

成功法则就是那19个字

 
 
 

日志

 
 

Unicode,UCS,UTF和字符集  

2010-07-22 11:25:06|  分类: R&D |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |
在计算机内部,所有的信息最终都表示为一个二进制的位串。

1.ASCII(American Standard Code for Information Interchange)
    最常用的编码标准。对英语字符与二进制位之间的关系做了统一规定,包含了字母、数字、标点符号和控制符。特点是用一个字节的后7位表示128个字符,最高位统一为0。

2.ANSI  
    各国为了适应自己的编码标准而制定的一种兼容ASCII的编码规范。比如中国的GB2312,台湾香港地区BIG5。日本的JIS0208,韩国的KSC5601等。这是各国针对本国语言制定的国家标准编码,在本国使用比较多。这些编码标准的编码库可能会互相冲突。而为了兼容这些冲突的编码,ANSI使用一种码页(code pages)的方式来实现切换。
但是这些ANSI码还是无法同时存在,因为它们的定义互相重叠,要自由使用不同语言就必须有一个新编码,为各种文字统一分配编码。
GB2312,GBK 通常称为国标码。这是中国等汉字地区使用的国家标准编码,是为了在计算机上实现汉字的显示统一制定的汉字字符集编码映射库。国标码使用2字节表示字符,英文同样使用2字节。不过是全角的英文。而为了和ascii兼容,半角的英文仍然只占用1字节。GB2312的原文还是区位码,从区位码到内码,需要在高字节和低字节上分别加上A0。在DBCS中,GB内码的存储格式始终是Big Endian,即高位在前。GB2312与UCS之间并无兼容关系,所以需要映射表将对应的码表与底层字库联系起来。


3.ISO8859系列
相对来说比较常见的一种编码,这是ISO组织开发的一个支持西欧各国文字的字符编码集,但不支持中文等亚洲文字。

4.Unicode字符集 (Universal Multiple-Octet Coded Character Set)
    Unicode提供了一种统一的编码方式,使任何语言的字符都可以为机器更容易的接受。包括JAVA、LDAP、XML这样的技术标准中均要求得到Unicode的支持。Unicode的字符被成为码位(CODE POINTS,就是可以分配给字符的数字。UTF-8、UTF-16、UTF-32都是将数字转换到程序数据的编码方案),用U+XXXX来表示(X为16进制的字符)。

    Unicode可以用来表示所有语言的字符,而且是定长编码,包括英文字母在内。相对于ISO8859-1编码来说,Unicode编码只是在前面增加了一个0字节。
需要说明的是,定长编码便于计算机处理,而Unicode又可以用来唯一表示所有字符,所以在很多软件内部是使用Unicode编码来处理的。

1).UCS(Unicode Character Set):
    这是Uicode在ISO的名称,目有两种格式:UCS-2和UCS-4。UCS-2(Unicode)用2个字节表示一个字符,UCS-4(Unicode-32) 用4个字节(实际上只用了31位,最高位必须为0)表示一个字符。UCS-4是由USC-2扩展来的,增加了2字节的高位。UCS-2可以表示2^16=65535个字符,基本上可以容纳所有常用各国字符,所以目前基本都使用UCS-2。

2).BMP(Basic Multilingual Plane):
    这是Unicode实际和字符对应的划分方式中的概念。
  UCS-2有2^16=65536个码位,UCS-4有2^31=2147483648个码位。
  UCS-4根据最高位为0的最高字节分成2^7=128个group
            每个group再根据次高字节分为 256个plane
            每个plane根据第3个字节分为256个row
            每行包含256个cells
  group 0的plane 0被称作Basic Multilingual Plane, 即BMP。或者说UCS-4中,高两个字节为0的码位被称作BMP。去掉0x0000的BMP上的UCS-4就变成了UCS-2编码。或者说UCS-2是USC-4的子集,BMP就是UCS-2在USC-4中的位置。我们从这里还可以得到USC-2转为UCS-4的方法,在UCS-2前面插入2个字节 0x0000。

3).Unicode的问题
    需要注意的是,Unicode只是一个符号集,它只规定了符号的二进制代码,却没有规定这个二进制代码应该如何编码存储。
这里有两个问题需要考虑,存储的空间效率(用尽可能少的字节表示)和符号的定界识别(如何才能区别Unicode和ASCII)是否容易

4).UTF(Ucs transformation format)
    是用来转换unicode编码的存储格式。分为UTF-8,UTF-16,UTF-32.
a).UTF-8 = Unicode Transformation Format -- 8 bit
        互联网上使用最广的一种Unicode的存储格式,即把Unicode文件转换成字节流传送。
        它的特点是可以完全兼容ASCII编码,是一种变长的编码方式。根据不同的符号而变化字节长度,节省存储空间。见下表
            Hex Min            Hex Max           Byte Sequence in Binary
            00000000           0000007F          0vvvvvvv
            00000080           000007FF          110vvvvv 10vvvvvv
            00000800           0000FFFF          1110vvvv 10vvvvvv 10vvvvvv
            00010000           001FFFFF          11110vvv 10vvvvvv 10vvvvvv 10vvvvvv
            00200000           03FFFFFF          111110vv 10vvvvvv 10vvvvvv 10vvvvvv 10vvvvvv
            04000000           7FFFFFFF          1111110v 10vvvvvv 10vvvvvv 10vvvvvv 10vvvvvv 10vvvvvv
        理论上UTF-8最大可以用6字节表示一个字符,但Unicode目前没有用大于0xffff的字符,实际UTF-8比较多地使用了4个字节。
        1字节的utf8为 ascii码,2字节的为西欧文字,3字节的为亚洲文字,4字节多为一些平面码。
        
        UTF-8的编码规则很简单:
        i).对于单字节的符号,字节的最高位设0,后面7位为这个符号的unicode码。
        ii).对于n字节的符号(n>1),第一个字节的前n位都设为1,第n+1位设为0,后续字节都用10开始。剩下的二进制位全部由符号的Unicode码的bit进行填充。
        (UTF-8还有一个好处就是,字符串处理程序仍然可以使用一个为0的字节来表示null-terminator,不会截断字符串)
        
        UTF-8转Unicode时使用第一个字节确定字节数,然后取出相应的位进行合成。


b).UTF-16
  UTF-16以16位无符号整数为单位编码。我们把Unicode编码记作U。编码规则如下:
  如果U<0x10000,U的UTF-16编码就是U对应的16位无符号整数。
  如果U≥0x10000,我们先计算U'=U-0x10000,然后将U'写成二进制形式:yyyy yyyy yyxx xxxx xxxx,U的UTF-16编码(二进制)就是:110110yyyyyyyyyy 110111xxxxxxxxxx。可见
        第一个WORD的取值范围是11011000 00000000到11011011 11111111,即0xD800-0xDBFF。
        第二个WORD的取值范围是11011100 00000000到11011111 11111111,即0xDC00-0xDFFF。
  为了将一个WORD的UTF-16编码与两个WORD的UTF-16编码区分开来,Unicode编码的设计者将0xD800-0xDFFF保留下来,并称为代理区(Surrogate):
  D800-DB7F High Surrogates(高位替代)
  DB80-DBFF High Private Use Surrogates(高位专用替代)
  DC00-DFFF Low Surrogates(低位替代)
  高位替代就是指这个范围的码位是两个WORD的UTF-16编码的第一个WORD。低位替代就是指这个范围的码位是两个WORD的UTF-16编码的第二个WORD。那么,高位专用替代是什么意思?如果一个字符的UTF-16编码的第一个WORD在0xDB80到0xDBFF之间,那么它的Unicode编码在什么范围内?我们知道第二个WORD的取值范围是0xDC00-0xDFFF,所以这个字符的UTF-16编码范围应该是 0xDB80 0xDC00到0xDBFF 0xDFFF。我们将这个范围写成二进制:
  1101101110000000 11011100 00000000 - 1101101111111111 1101111111111111
  按照编码的相反步骤,取出高低WORD的后10位,并拼在一起,得到
  1110 0000 0000 0000 0000 - 1111 1111 1111 1111 1111
  即0xe0000-0xfffff,按照编码的相反步骤再加上0x10000,得到 0xf0000-0x10ffff。这就是UTF-16编码的第一个WORD在0xdb80到0xdbff之间的Unicode编码范围,即平面15和平面16。因为Unicode标准将平面15和平面16都作为专用区,所以0xDB80到0xDBFF之间的保留码位被称作高位专用替代。
        由于实际使用的UCS2,或者UCS4的BMP必然小于0x10000,所以就目前而言,可以认为UTF-16和UCS-2基本相同。


c).UTF-32
        UTF-32编码以32位无符号整数为单位。Unicode的UTF-32编码就是其对应的32位无符号整数。


5).BOM(Byte Order Mark)
    Unicode码可以采用UCS-2/UCS-4的格式直接存储。那么很自然的一个问题就是:计算机怎么知道某一个文件到底采用哪一种字节序方式编码?
Unicode规范中建议,每一个文件的最前面分别加入一个表示编码顺序的字符,这个字符的名字叫做"零宽度非换行空格"(ZERO WIDTH NO-BREAK SPACE),用FEFF表示(FFFE在UCS中是不存在的字符)。或者在传输字节流前,先传输此字符。
如果一个文本文件的头两个字节是FE FF,就表示该文件采用Big endian;如果头两个字节是FF FE,就表示该文件采用Little endian。
UTF-8不需要BOM来说明字节序,但可以用BOM标志编码方式。遇到带0xEFBBBF开头的文本,计算机就可以直接按UTF-8编码处理。

  UTF        Byte Order Mark
  UTF-8      EF BB BF
  UTF-16LE   FF FE
  UTF-16BE   FE FF
  UTF-32LE   FF FE 00 00
  UTF-32BE   00 00 FE FF
  评论这张
 
阅读(892)| 评论(0)
推荐 转载

历史上的今天

在LOFTER的更多文章

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017