随笔 - 96  文章 - 255  trackbacks - 0
<2010年6月>
303112345
6789101112
13141516171819
20212223242526
27282930123
45678910

E-mail:zbln426@163.com QQ:85132383 长期寻找对战略游戏感兴趣的合作伙伴。

常用链接

留言簿(21)

随笔分类

随笔档案

SDL相关网站

我的个人网页

我的小游戏

资源下载

搜索

  •  

积分与排名

  • 积分 - 488878
  • 排名 - 37

最新评论

阅读排行榜

评论排行榜

<本文PDF文档下载>

Unicode和UCS

Unicode和UCS是两个独立的组织分别制定的一套编码标准,但是因为历史的原因,这两套标准是完全一样的。Unicode这个词用得比较多的原因可能是因为比较容易记住,如果没有特别的声明,在本文所提及的Unicode和UCS就是一个意思。Unicode的目标是建立一套可以包含人类所有语言文字符号你想得到想不到的各种东西的编码,其编码容量甚至预留了火星语以及银河系以外语言的空间——开个玩笑,反正简单的说,Unicode编码集足够的大,如果用计算机单位来表示,其数量比3个字节大一些,不到4个字节。

Unicode和UTF

因为Unicode包含的内容太多,其编码在计算机中的表示方法就成为了一个有必要研究的问题。传统编码,比如标准的7位ASCII,在计算机中的表示方法就是占一个字节的后7位,这似乎是不需要解释就符合大家习惯的表示方法。但是当今Unicode的总数达到32位(计算机的最小单位是字节,所以大于3字节,就只能至少用4字节表示),对于大部分常用字符,比如Unicode编码只占一个字节大小的英语字母,占两个字节大小汉字,都用4个字节来储存太奢侈了。另外,如果都用4字节直接表示,就不可避免的出现为0的字节。而我们知道,在C语言中,0x00的字节就是'\0',表示的是一个字符串(char字符串,非wchar_t)的结束,换句话说,C风格的char字符串无法表示Unicode。
因为类似的种种问题,为Unicode在计算机中的编码方法出现了,这就是UTF;所对应的,为UCS编码实现的方式也有自己的说法。一般来说,UTF-x,x表示这套编码一个单位至少占用x位,因为Unicode最长达到32位,所以UTF-x通常是变长的——除了UTF-32;而UCS-y表示一个单位就占用y个字节,所以能表示当今Unicode的UCS-y只有UCS-4,但是因为历史的原因,当Unicode还没那么庞大的时候,2个字节足够表示,所以有UCS-2,现在看来,UCS-2所能表示的Unicode只是当今Unicode的一个子集。
也就是说,如果某种编码,能根据一定的规则算法,得到Unicode编码,那么这种编码方式就可以称之为UTF。

UTF-8和Windows GB2312

UTF-8是一套“聪明”的编码,可能用1,2,3,4个字节表示。通过UTF-8的算法,每一个字节表示的信息都很明确:这是不是某个Unicode编码的第一个字节;如果是第一个字节,这是一个几位Unicode编码。这种“聪明”被称为UTF-8的自我同步,也是UTF-8成为网络传输标准编码的原因。
另外,UTF-8也不会出现0字节,所以可以表示为char字符串,所以可以成为系统的编码。Linux系统默认使用UTF-8编码。
Windows GB2312一般自称为GB2312,其实真正的名字应该是Windows Codepage 936,这也是一种变长的编码:1个字节表示传统的ASCII部分;汉字部分是两个字节的GBK(国标扩(展),拼音声母)。Codepage 936也可以表示为char字符串,是中文Windows系统的默认编码。
我们在第1节中看到的
const char* s = "中文abc";
在Windows中的编码就是Codepage 936;在Linux中的编码就是UTF-8。
需要注意的是,Codepage 936不像UTF,跟Unicode没有换算的关系,所以只能通过“代码页”技术查表对应。

UTF-16和UCS-2

UTF-16用2个字节或者4个字节表示。在2个字节大小的时候,跟UCS-2是一样的。UTF-16不像UTF-8,没有自我同步机制,所以,编码大位在前还是小位在前,就成了见仁见智的问题。我们在第1节中,“中”的UCS-2BE(因为是两个字节,所以也就是UTF-16BE)编码是0x4E2D,这里的BE就是大位在后的意思(也就是小位在前了),对应的,如果是UCS-2LE,编码就成了0x2D4E。
Windows中的wchar_t就是采用UCS-2BE编码。需要指出的是,C++标准中对wchar_t的要求是要能表示所有系统能识别的字符。Windows自称支持Unicode,但是其wchar_t却不能表示所有的Unicode,由此违背了C++标准。

UTF-32和UCS-4

UTF-32在目前阶段等价于UCS-4,都用定长的4个字节表示。UTF-32同样存在BE和LE的问题。Linux的wchar_t编码就是UTF-32BE。在16位以内的时候,UTF-32BE的后两位(前两位是0x00 0x00)等价于UTF-16BE也就等价于UCS-2BE

BOM

为了说明一个文件采用的是什么编码,在文件最开始的部分,可以有BOM,比如0xFE 0xFF表示UTF-16BE,0xFF 0xFE 0x00 0x00表示UTF-32LE。UTF-8原本是不需要BOM的,因为其自我同步的特性,但是为了明确说明这是UTF-8(而不是让文本编辑器去猜),也可以加上UTF-8的BOM:0xEF 0xBB 0xBF

以上内容都讲述得很概略,详细信息请查阅维基百科相关内容。
posted on 2010-06-25 21:51 lf426 阅读(3573) 评论(1)  编辑 收藏 引用 所属分类: 语言基础、数据结构与算法

FeedBack:
# re: 彻底解密C++宽字符:2、Unicode和UTF 2013-08-07 07:25 ligand
你理解得大端序、小端序,名称弄反了吧。

Windows是著名的小端序,包wchar_t就是采用UTF-16LE编码. 参见“字节序”的中英文维基。  回复  更多评论
  

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理