2010年11月12日星期五

UNICODE中文编码

最近想把上学期短信程序中的编码部分改一改,于是这几天就结合上学期的经验把中文编码问题又分析了分析,把中文整个从编码到显示所有设计到的问题列了一个流程,就从最基础的编码问题开始,当下最为流行的莫过于UNICODE编码方式了,这里我们就以UNICODE编码展开正文。
我们知道计算机的第一个编码标准是ASCII编码,我们学习过C语言的人肯定都会对这个编码标准很熟悉,ASCII使用一个字节共可以表示256个字符。随着计算机的普及非英文语言的国家也要开始使用计算机,就遇到了自己国家的字符在计算机中显示的问题,于是各国不同的各种各样的字符标准就诞生了,中国的有GB、GBK、BIG5等。但是这是也出现了一个编码识别和编码冲突问题。英语国家的计算机用户打开还有非英文编码的文档显示的肯定都是乱码,因为他识别不了。多种多样的编码给软件的设计带来了很大的麻烦,尤其服务器软件(他要能区分不同的编码,并给予相应编码的回复,很复杂)。于是统一编码格式UNICODE就应运而生了,他解决了先前的编码问题。
UNICODE的字符集可以简写为UCS(Unicode Character Set),有USC-2 和USC-4两个标准,分别使用2个字节和4个字节表示。也就是说USC-2可以表示2^16 = 65536(0~65535)个字符,现在大部分使用的是USC-2,随着更多文字的加入会逐步扩展到USC-4。比如汉字的“汉”的UNICODE编码为27721(0×6c49)。但是这时候使用英文的国家就不干了,人家原来使用8位可以表示的字符现在非要用16位或者32位表示。比如呀原来的ASCII为00111111现在却要用0000000000111111表示,浪费了大量的空间,这样就要使用我们经常听到的UTF-8,UTF-16,UTF-32了。

UTF为“UCS Transformation Format”的缩写,这些负责将UNICODE表示的数据转换为程序更为方便使用和存储的格式:UTF-8,UTF-16,UTF-32。下面以UTF-8为例,了解英文和中文字符的UNICODE编码向UTF-8表示的转化过程。
UTF-8以字节为单位对Unicode进行编码。从Unicode到UTF-8的编码方式如下:
  Unicode编码(16进制) ║ UTF-8 字节流(二进制)
  000000 - 00007F ║ 0xxxxxxx
  000080 - 0007FF ║ 110xxxxx 10xxxxxx
  000800 - 00FFFF ║ 1110xxxx 10xxxxxx 10xxxxxx
  010000 - 10FFFF ║ 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
UTF-8的特点是用不定长的字符数对不同的编码进行表示。对于在000000 - 00007F之间的英文字符,UTF-8 的表示方式和原来ASCII的表示方式完全相同。
例如一个字母的UNICODE编码为0×65,二进制为01100101,UTF-8编码就为01100101。
汉字“汉”的编码为0×6c49,在000800 - 00FFFF之间,就需要用三个字节来表示。又0×6c49的二进制表示为110110001001001,将二进制位左端补0,凑够1110xxxx 10xxxxxx 10xxxxxx中的x的个数位共16位,然后替换掉x,就是汉字“汉”的UTF-8编码:11100110 10110001 10001001,即E6 B1 89。。
目前大部分的计算机都已经支持UNICODE编码,我们可以很方便的浏览其他国家的文字,看到的而不是乱码。UNICODE编码的实现编码目前使用比较多的为UTF-8,当然也有使用UTF-16和UTF-32,但是在使用后两种时就需要考虑计算机系统的大小端的问题。
“汉字”对应的数字是0×6c49和0×5b57,而编码的程序数据是:
BYTE data_utf8[] = {0xE6, 0xB1, 0x89, 0xE5, 0xAD, 0x97}; // UTF-8编码
WORD data_utf16[] = {0x6c49, 0x5b57}; // UTF-16编码
DWORD data_utf32[] = {0x6c49, 0x5b57}; // UTF-32编码

没有评论:

发表评论