分享

彻底解密C 宽字符:2、Unicode和UTF

 Foxmouse 2012-03-14
<本文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

以上内容都讲述得很概略,详细信息请查阅维基百科相关内容。

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多