字符编码-ASCII GB2312 GBK GB13080 UNICODE UTF
(2014-12-31 17:10:41)分类: C |
字符:字符是文字与符号的总称,包括文字、图形符号、数学符号等。
字符集:常常和一种具体的语言文字对应起来,该文字中的所有字符或者大部分常用字符就构成了该文字的字符集,比如英文字符集,中文字符集,日文字符集等。
字符编码:计算机要处理各种字符,就需要将字符和二进制内码对应起来,这种对应关系就是字符编码。
一.几种常用的编码。
1)ASCII码是7位编码,编码范围是0x00-0x7F。ASCII字符集包括英文字母、阿拉伯数字和标点符号等字符。其中0x00-0x20和0x7F共33个控制字符。只支持ASCII码的系统会忽略每个字节的最高位,只认为低7位是有效位。HZ字符编码就是早期为了在只支持7位ASCII系统中传输中文而设计的编码。早期很多邮件系统也只支持ASCII编码,为了传输中文邮件必须使用BASE64或者其他编码方式。
2)GB2312。我们聪明的中国人一眼就看出博大精深的中文字符怎么编码呢?这么简单的一个字节你能表示中文字符!别做梦了!谁让我们聪明呢,一个字符不行,可以用两个表示。聪明的程序员就提出了用两个字节表示一个中文字符。那么问题又出来了,怎么区分英文字符和中文字符呢?难道cpu是智能的不成?不,cup不是神仙,聪明的程序员把中文字符的两个字节的第一位设置为1,这样在处理中英文混和的字符时,只要发现某个字节的首位是1,就把两个字节表示为一个字符。说到这里,也许你已有点那么个明白的意思了。原来如此,GB2312也只不过是按照和ASCII相同的处理方式对字符处理,只不过是对中文有了两个字符,英文还和ASCII字符集的编码相同占一个字符。说了如此之多,才仅仅对GB2312一点点理解而已,请看下面对GB2312的说明:
GB2312是基于区位码设计的,区位码把编码表分为94个区,每个区对应94个位,每个字符的区号和位号组合起来就是该汉字的区位码。区位码一般用10进制数来表示,如1601就表示16区1位,对应的字符是“啊”。在区位码的区号和位号上分别加上0xA0就得到了GB2312编码。区位码中01-09区是符号、数字区,16-87区是汉字区,10-15和88-94是未定义的空白区。它将收录的汉字分成两级:第一级是常用汉字计3755个,置于16-55区,按汉语拼音字母/笔形顺序排列;第二级汉字是次常用汉字计3008个,置于56-87区,按部首/笔画顺序排列。一级汉字是按照拼音排序的,这个就可以得到某个拼音在一级汉字区位中的范围,很多根据汉字可以得到拼音的程序就是根据这个原理编写的。
3)GBK
4)
5)Unicode。Unicode可以说是计算机字符编码的一个伟大变革,之所以说它伟大,就像大家说秦始皇伟大一样,秦始皇不但统一了六国,更统一了文字和钱币。那么Unicode可以说是世界上任何字符的一个集合。Unicode为每个字符提供了唯一的特定数值,不论在什么平台上、不论在什么软件中,也不论什么语言。也就是说,它把世界上使用的所有字符都列出来,并给每一个字符一个唯一特定数值。
6) utf-8。由于Unicode是一种双字节编码,可能有些非常不常用的字符再加到Unicode字符集了,两位字节都无法表示,因而可能需四个字节表示。这样,如果统一使用Unicode作为一种编码方式,确实太浪费。那么聪明的人类就想出了用utf系列的方式来编码unicode,也就是说utf8是对unicode的一种存储和传输编码方式。UTF-8最大的一个特点,就是它是一种变长的编码方式。它可以使用1~多个字节表示一个符号,根据不同的符号而变化字节长度。他是怎么样编码的呢?UTF-8的编码规则很简单,只有二条:
a.对于单字节的符号,字节的第一位设为0,后面7位为这个符号的unicode码。因此对于英语字母,UTF-8编码和ASCII码是相同的。
b.对于n字节的符号(n>1),第一个字节的前n位都设为1,第n+1位设为0,后面字节的前两位一律设为10。剩下的没有提及的二进制位,全部为这个符号的unicode码。
下表总结了编码规则,字母x表示可用编码的位。
Unicode符号范围
(十六进制) |
0000 0000-0000 007F | 0xxxxxxx
0000 0080-0000 07FF | 110xxxxx10xxxxxx
0000 0800-0000 FFFF | 1110xxxx10xxxxxx 10xxxxxx
0001 0000-0010 FFFF | 11110xxx10xxxxxx 10xxxxxx 10xxxxxx
下面,以汉字“严”为例,演示如何实现UTF-8编码。
已知“严”的unicode是4E25(100111000100101),根据上表,可以发现4E25处在第三行的范围内(00000800-0000 FFFF),因此“严”的UTF-8编码需要三个字节,即格式是“1110xxxx 10xxxxxx 10xxxxxx”。然后,从“严”的最后一个二进制位开始,依次从后向前填入格式中的x,多出的位补0。这样就得到了,“严”的UTF-8编码是“11100100 10111000 10100101”,转换成十六进制就是E4B8A5。
7)utf-16,utf-32。Utf-16和utf-32分别是Unicode的16位和32位编码方式。考虑到最初的目的,通常说的Unicode就是指utf-16(也就是说两位字节的unicode版本正好可以用utf-16体现,既utf-16的编码就是unicode码本身)。
二.对以上几中编码的一个总结:
1)我们可以把上面的ascii,gb2312, gbk, gb13080看成同一系列的编码,即从后往前都是兼容的,都是对原ascii中对应的字符采取一位编码,其他字符采取双字节编码。这几类编码可以统一理解位ascii系列的编码(本人自造的名词),因为他们在编程语言,甚至计算机处理过程种都是一样的。
2)utf-8, utf-16, utf-32可以归纳位unicode系列的编码,因为这三种编码计算机中要找到他们对应的字符的话,都是对应到他们所表示的unicode码所对应的字符。
3)utf-8中对应的原ascii中的编码和第1)项中里面涉及到的编码也是相同的,即对英文字符都是兼容的,为一个字节。
4)不要太过多的关注Unicode到底是一种字符集还是一种编码。这个概念网络上有的说的很绝对,即unicode只是一种字符集,不是一种编码。但是如果编码和其unicode值完全相同,我们把unicode认为是一种编码又有什么关系呢?况且windows中的记事本程序中就完全把文件保存成unicode编码格式的选项。如果非要硬说unicode只是一种字符集合,那么我们可以认为utf-16是我们平常所说的unicode编码。
三.程序开发,编译环境中采用的字符编码
其实这个问题很明确,在VC中,支持两种编码,一种是unicode形式的,一种是ascii形式的编码。比如你可以定义一个CString
str1= “a中国”,这个str1会默认的编译为ascii形式。而如果你写成
http://blog.csdn.net/vcrwx/article/details/7656995