关于编码ansi,unicode,utf-8,utf-16.GB2312
最初,
ASCII字符集,它使用7 bits来表示一个字符,总共表示128个字符,其中包括了英文字母、数字、标点符号等常用字符。
之后,又进行扩展,使用8 bits表示一个字符,可以表示256个字符,主要在原来的7 bits字符集的基础上加入了一些特殊符号例如制表符。
为了能够表示其它国家的文字,各国在ASCII的基础上制定了自己的字符集,这些从ANSI标准派生的字符集被习惯的统称为ANSI字符集,它们正式的名称应该是MBCS(Multi-Byte Chactacter System,即多字节字符系统)。这些派生字符集的特点是以ASCII 127 bits为基础,兼容ASCII 127,他们使用大于128的编码作为一个Leading Byte,紧跟在Leading Byte后的第二(甚至第三)个字符与Leading Byte一起作为实际的编码。这样的字符集有很多,我们常见的GB-2312就是其中之一。
传统的C风格的字符串是以字符 '\0 '为结尾的一系列字节的集合,其一个单元为char类型,可以保存世界上的几百种不同的字符集,包括ASCII、ISO-8859、GBK、BIG-5、SHIFT-JIS、UTF-8等等。通常这些字符集都是兼容ASCII字符集的。我们可以把这些兼容ASCII字符集统称为ANSI字符集。
例如在GB-2312字符集中,“连通”的编码为C1 AC CD A8,其中C1和CD就是Leading Byte。前127个编码为标准ASCII保留,例如“0”的编码是30H(30H表示十六进制的30)。软件在读取时,如果看到30H,知道它小于128就是标准ASCII,表示“0”,看到C1大于128就知道它后面有一个另外的编码,因此C1 AC一同构成一个整个的编码,在GB-2312字符集中表示“连”。而其UTF-8编码为:E8 BF 9E E9 80 9A。
为什么使用UTF-8?
1. 为了双字节的Unicode能够在现存的处理单字节的系统上正确传输,出现了UTF-8;
2. ASCII转换成UCS-2,只是在编码前插入一个0x0。用这些编码,会包括一些控制符,比如 或 /,这在UNIX和一些C函数中,将会产生严重错误。因此可以肯定,UCS-2不适合作为Unicode的外部编码;
3. UTF-16与UTF-32相比,UTF-16显得更加简洁。Windows下普遍使用UTF-16,而Linux和其它Unix类的系统由于历史上的设计原因,则比较倾向于使用UTF-8和UTF-32这两种传输方式。
关于BOM:
BOM(Byte order Mark)是一个字符,它表明UNICODE文本的UTF-16,UTF-32的编码字节顺序(高字节低字节顺序)和编码方式(UTF-8,UTF-16,UTF-32, 其中UTF-8编码是字节顺序无关的)。
EF BB BF UTF-8
FF FE UTF-16/UCS-2, little endian
FE FF UTF-16/UCS-2, big endian
FF FE 00 00 UTF-32/UCS-4, little endian.
00 00 FE FF UTF-32/UCS-4, big-endian.
详见:http://www.unicode.org/faq/utf_bom.html
目前常用的一些编码方案
1、在中国,大陆最常用的就是GBK18030编码,除此之外还有GBK,GB2312,这几个编码的关系是这样的。
最早制定的汉字编码是GB2312,包括6763个汉字和682个其它符号95年重新修订了编码,命名GBK1.0,共收录了21886个符号。之后又推出了GBK18030编码,共收录了27484个汉字,同时还收录了藏文、蒙文、维吾尔文等主要的少数民族文字,现在WINDOWS平台必需要支持GBK18030编码。
按照GBK18030、GBK、GB2312的顺序,3种编码是向下兼容,同一个汉字在三个编码方案中是相同的编码。
2、台湾,香港等地使用的是BIG5编码。
3、日本:SJIS编码。
UTF-8到Unicode的转换:
例:
E4 BD A0 11100100 10111101 10100000
这是“你”字的UTF-8编码
4F 60 01001111 01100000
这是“你”的Unicode编码
按照UTF-8的编码规则,分解如下:xxxx0100 xx111101 xx100000
把除了x之外的数字拼接在一起,就变成“你”的Unicode编码。
注意UTF-8的最前面3个1,表示整个UTF-8串是由3个字节构成的。
经过UTF-8编码之后,再也不会出现敏感字符了,因为最高位始终为1。
以下是Unicode和UTF-8之间的转换关系表:
U-00000000 - U-0000007F: 0xxxxxxx
U-00000080 - U-000007FF: 110xxxxx 10xxxxxx
U-00000800 - U-0000FFFF: 1110xxxx 10xxxxxx 10xxxxxx
U-00010000 - U-001FFFFF: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
U-00200000 - U-03FFFFFF: 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
U-04000000 - U-7FFFFFFF: 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
Unicode编码转换到UTF-8,简单的把Unicode字节流套到x中就变成UTF-8。
ISO 8859系列字符集
ISO 8859系列字符集是欧洲计算机制造商协会(ECMA)在上世纪80年代中期设计,并被国际标准化(ISO)组织采纳为国际标准。ISO 8859系列字符集目前有15个字符集,包括:
* ISO 8859-1 大部分的西欧语系,例如英文、法文、西班牙文和德文等(Latin-1)
* ISO 8859-2 大部分的中欧和东欧语系,例如捷克文、波兰文和匈牙利文等(Latin-2)
* ISO 8859-3 欧洲东南部和其它各种文字(Latin-3)
* ISO 8859-4 斯堪的那维亚和波罗的海语系(Latin-4)
* ISO 8859-5 拉丁文与斯拉夫文(俄文、保加利亚文等)
* ISO 8859-6 拉丁文与阿拉伯文
* ISO 8859-7 拉丁文与希腊文
* ISO 8859-8 拉丁文与希伯来文
* ISO 8859-9 为土耳其文修正的Latin-1(Latin-5)
* ISO 8859-10 拉普人、北欧与爱斯基摩人的文字(Latin-6)
* ISO 8859-11 拉丁文与泰文
* ISO 8859-13 波罗的海周边语系,例如拉脱维亚文等(Latin-7)
* ISO 8859-14 凯尔特文,例如盖尔文、威尔士文等(Latin-8)
* ISO 8859-15 改进的Latin-1,增加遗漏的法文、芬兰文字符和欧元符号(Latin-9)
* ISO 8859-16 罗马尼亚文(Latin-10)
其中缺少的编号12据说是为了预留给天城体梵文字母(Deva-nagari)的。印地文和尼泊尔文都使用了这种在七世纪形成的字母表。由于印度定义了自己的编码ISCII(Indian Script Code for Information Interchange),所以这个编号就未被使用。ISO 8859系列字符集都是单字节字符集,即只使用0x00-0xFF对字符编码。
绝大多数字符集都与ASCII编码保持兼容,ISO 8859系列字符集也不例外,它们的0x00-0x7f都与ASCII码保持一致,各字符集的不同之处在于如何利用0x80-0xff的码位。
wchar_t和不同平台下的Unicode(Win32和UNIX)
C/C++标准均已经提供了wchat_t关键字来实现对Unicode的支持,而且wchat_t类型只用于Unicode编码。在Windows平台下,wchat_t类型是16位的;而在Linux下,wchat_t类型是32位的。
下面以Windows x86平台下为例子,说明wchar_t字符串在内存中的存储形式:
例如下面一个UTF-16字符串:
wchar_t str[]=L "中文 ";
上面是一个UTF-16的字符串,是分别由0x4E2D,0x6587,0x0000所组成的串。因为x86的CPU是低字节在前的(Little Endian),所以该wchar_t串在内存中的存储为:2D 4E 87 65 00 00。
Unicode在C/C++中就是这么简单的表示用法,在某些的C/C++编译器中,却不能完善支持,下面就列举各C/C++编译器对wchar_t字符和字符串的支持程度:
(1)Visual C/C++
Visual C/C++的编译器对Unicode的支持是最完美的,Microsoft是Unicode的创造者之一,也是极力推荐使用Unicode编码的公司。Visual C/C++除了完美支wchar_t类型外,Visual C++ 7.0或者更新版本的编译器还可以接受UTF-8/UTF-16编码格式的源代码文件。
(3)gcc
GNU C/C++编译器也可以正确支持wchar_t字符和字符串,但是源代码的保存格式必须符合下面条件:
一、源代码文件的保存编码必须是UTF-8
二、UTF-8编码格式的源代码文件,不能有BOM标志头。
只有源代码文件符合上面两个条件,gcc才会正确支持wchar_t字符和字符串。如果不符合上面两个条件的话,有可能会编译出错,有可能会产生错误的wchar_t字符和字符串。
gcc在Windows平台下,wchar_t是16位类型,在Linux平台下,wchar_t是32位类型。
浙公网安备 33010602011771号