【转】【编码】ASCII 、UNICODE和UTF-8之二
字符发展
1. 美国
ASCII-(American standard code information interchange) 美国信息互换标准代码
范围:1-127 ; 单字
备注:前部用作控制码,0x20以下的字节状态称为"控制码";后面跟数字,字母大小写至127
2. 美国
ASCII扩展编码
范围:128-255; 单字
备注:很多画表格时需要用下到的横线、竖线、交叉等形状,一直把序号编到了最后一 个状态255
3. 中国GB2312
原由:中国人们得到计算机时,有6000多个常用汉字需要保存呢
规定:一个小于127的字符的意义与原来相同,但两个大于127的字符连在一起时,就表示一个汉字,
前面的一个字节(他称之为高字节)从0xA1用到 0xF7,后面一个字节(低字节)从0xA1到0xFE,
这样我们就可以组合出大约7000多个简体汉字了
范围:0xA1A1~0xF7FE;双字
备注:连在 ASCII 里本来就有的数字、标点、字母都统统重新编了两个字节长的编码,
这就是常说的"全角"字符,而原来在127号以下的那些就叫"半角"字符了
4. 中国GBK
原由:但是中国的汉字太多了,我们很快就就发现有许多人的人名没有办法在这里打出来
规定:于是干脆不再要求低字节一定是127号之后的内码,只要第一个字节是大于127就固定表示这是一个汉字的开始
范围:0xA100~0xFFFF双字
备注:GBK兼容GB2312, 此时20000个新的汉字(包括繁体字)和符号
后来少数民族也要用电脑了,于是我们再扩展,又加了几千个新的少数民族的字,GBK 扩成了GB18030
5. 双字时代
我们看到这一系列汉字编码的标准是好的,于是通称他们叫做 "DBCS"(Double Byte Charecter Set 双字节字符集)
原因:台湾出现BIG5;日本出现了XXX
ISO - (international standard orginaztion) 国际标谁化组织 的出现, 提出规范化编码措施
废除所有地区编码规范,提出统一编码原则
6. UNICODE (Universal Multiple-Octet Coded Character Set",简称 UCS)
规定:于是 ISO 就直接规定必须用两个字节,也就是16位来统一表示所有的字符,
对于ascii里的那些“半角”字符,UNICODE 包持其原编码不变,
只是将其长度由原来的8位扩展为16位,而其他文化和语言的字符则全部重新统一编码。
由于"半角"英文符号只需要用到低8位,所以其高 8位永远是0,
英文文本时会多浪费一倍的空间。
范围:0x0000~0xFFFF双字
备注:他们为了在不同的国家销售同一套软件,
就不得不在区域化软件时也加持那个双字节字符集咒 语,
不仅要处处小心不要搞错,
还要把软件中的文字在不同的字符集中转来转去。UNICODE 对于他们来说是一个很好的一揽子解决方案
,于是从 Windows NT 开始,MS 趁机把它们的操作系统改了一遍,
把所有的核心代码都改成了用 UNICODE 方式工作的版本,
从这时开始,WINDOWS 系统终于无需要加装各种本土语言系统,就可以显示全世界上所有文化的字符了。
UNICODE 在制订时没有考虑与任何一种现有的编码方案保持兼容;
这使得 GBK 与UNICODE 在汉字的内码编排上完全是不一样的,这种转换必须通过查表来进行。
7. 网络数据交换时代
UNICODE -2 (65535) 二字节(简写UCS-2)
UNICODE - 4 (....) 四节节(简写UCS-4)
A)、字符是如何保存在内存中的呢?
在字符或字符串前加L表示后面跟的是UNICODE
wchar_t wch = L'1'; // 2 bytes, 0x0031
wchar_t* wsz = L"Hello"; // 12 bytes, 6 wide characters
1)、单字节字符串都是字符一一保存,以0结尾。
"Bob" 内存中形式为:
42 6F 62 00
B o b EOS
2)、Big Endian和Little Endian
上面提到了一个字符可能占用多个字节,那么这多个字节在计算机中如何存储呢?比如字符0xabcd,它的存储格式到底是 AB CD,还是 CD AB 呢?
实际上两者都有可能,并分别有不同的名字。如果存储为 AB CD,则称为Big Endian;如果存储为 CD AB,则称为Little Endian。
具体来说,以下这种存储格式为Big Endian,因为值(0xabcd)的高位(0xab)存储在前面:
系统开发者应该对Little-endian和Big-endian模式非常了解。采用Little-endian模式的CPU对操作数的存放方式是 从低字节到高字节,
而Big-endian模式对操作数的存放方式是从高字节到低字节。
例如,16bit宽的数0x1234在Little-endian 模式CPU内存中的存放方式(假设从地址0x4000开始存放)为:
内存地址 0x4000 0x4001
存放内容 0x34 0x12
而在Big-endian模式CPU内存中的存放方式则为:
内存地址 0x4000 0x4001
存放内容 0x12 0x34
32bit宽的数0x12345678在 Little-endian模式CPU内存中的存放方式(假设从地址0x4000开始存放)为:
内存地址 0x4000 0x4001 0x4002 0x4003
存放内容 0x78 0x56 0x34 0x12
而在Big-endian 模式CPU内存中的存放方式则为:
内 存地址 0x4000 0x4001 0x4002 0x4003
存放内容 0x12 0x34 0x56 0x78
3)、任何文字在Unicode中都对应一个值,这个值称为代码点(code point)。
规定存储方式的称为UTF(Unicode Transformation Format),其中应用较多的就是UTF-16和UTF-8了。
UTF-16BE和UTF-16LE不难理解,而UTF-16就需要通过在文件开头以名为BOM(Byte Order Mark)的字符来表明文件是Big Endian还是Little Endian。
BOM为U+FEFF这个字符。
举个例子。“ABC”这三个字符用各种方式编码后的结果如下:
UTF-16BE 00 41 00 42 00 43
UTF-16LE 41 00 42 00 43 00
UTF-16(Big Endian) FE FF 00 41 00 42 00 43
UTF-16(Little Endian) FF FE 41 00 42 00 43 00
UTF-16(不带BOM) 00 41 00 42 00 43
4)、UTF-8
UTF-16和UTF-32的一个缺点就是它们固定使用两个或四个字节,这样在表示纯ASCII文件时会有很多00字节,造成浪费。而RFC3629定义的UTF-8则解决了这个问题。
UTF-8用1~4个字节来表示代码点。表示方式如下:
Unicode是一个字符集,而UTF-8是Unicode的其中一种,Unicode是定长的都为双字节,而UTF-8是可变的,
对于汉字来说Unicode占有的字节比UTF-8占用的字节少1个字节。Unicode为双字节,而UTF-8中汉字占三个字节。
UTF-8编码字符理论上可以最多到6个字节长,然而16位BMP(Basic Multilingual Plane)字符最多只用到3字节长。下面看一下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