ICU以及字符编码的介绍

[1] ICU编程接口的文档:http://userguide.icu-project.org/

[2] UTF8编码介绍:http://zh.wikipedia.org/wiki/UTF-8

[3] 字符集GBK和UTF8的区别说明:http://blog.itpub.net/55022/viewspace-713901

项目中,我需要压力测试一段ICU封装函数的代码,即找到一段GBK编码出错,UTF8编码成功的字符序列;和一段GBK编码,UTF8编码都出错的字符序列。

以前对编码一知半解的我,甚至认为unicode就是utf8。。。

1、  unicode就是用2个字节表示全球所有的字符,也就是每个字符都是2个字节。MFC的_T()就是把字符串用unicode编码,然后在不同的操作系统平台上转换成不同的编码显示方式,适应软件的全球化。

2、  ASCII是最简单的编码方式,字节高位为0,只有1个字节。在unicode下,ASCII的字符也是2个字节的,但是洋人为了节约自己的存储空间、减少传输容量等,就设计了UTF8的编码。

3、  UTF8编码是与unicode一一对应的编码方式,在UTF8下,ASCII字符是1个字节的,但是中文却变成了3、4个字节。然后中国人又不愿意了,设计了GBK编码,使中文用2个字节编码表示,这是后话了。

这是unicode/UTF8 之间的转换关系如下:

unicode(U+) UTF8
U+00000000 - U+0000007F: 0xxxxxxx
U+00000080 - U+000007FF: 110xxxxx10xxxxxx
U+00000800 - U+0000FFFF: 1110xxxx10xxxxxx10xxxxxx
U+00010000 - U+001FFFFF: 11110xxx10xxxxxx10xxxxxx10xxxxxx
U+00200000 - U+03FFFFFF: 111110xx10xxxxxx10xxxxxx10xxxxxx10xxxxxx
U+04000000 - U+7FFFFFFF: 1111110x10xxxxxx10xxxxxx10xxxxxx10xxxxxx10xxxxxx

比如: "我" 的unicode编码为 "U+6211"(01100010 00010001),在U+00000800 - U+0000FFFF之间,所以采用三字节编码,按规则分段为:0110 001000 010001,再分别替换上表中的x,得到11100110 10001000 10010001,即为 "E6 88 91",这就是 "我" 的UTF-8编码。 

4、  GBK用2个字节表示中文字符,1个字节表示ASCII字符。也就是用了UTF8类似编码方式的简化版,规定中文最高位都为1,ASCII最高位都为0。当用GBK解码时,若高字节最高位为0,则用ASCII码表解码;若高字节最高位为1,则用GBK编码表解码。

一开始,我怎么也找不到GBK编码失败,UTF8编码成功的方法,基本已经打算放弃,因为GBK编码把多字节的UTF8字符分割成了两个两个的单元,强行进行了编码。但是当我看到“GBK的整体编码范围是为0x8140-0xFEFE,不包括低字节是0x7F的组合。高字节范围是0×81-0xFE,低字节范围是0x40-7E和0x80-0xFE”,我重新燃起了希望,这简直就是留了GBK与UTF8编码区别的后门。

比如这句:

char pMData[11] = {'a', 'b', 'c', 'xE6', 'x88', 'x91', 'x7F', 'd', 'e'};

UTF8编码时把它分为('xE6', 'x88', 'x91')和('x7F'),而GBK把它分成了('xE6', 'x88')和('x91', 'x7F'),而('x91', 'x7F')导致了GBK编码的失败。

再比如这句:

char pMData[11] = {'a', 'b', 'c', 'xEE', 'xEE', 'xEE', 'x7F', 'd', 'e'};

UTF8编码将其分为('xEE', 'xEE', 'xEE'),('x7F'),其中('xEE', 'xEE', 'xEE')的第一个字符为E,其编码格式应该为1110xxxx10xxxxxx10xxxxxx,即第3个字符只可能为8,9,A,B,而不可能是E(画红色背景的那个字符),因而UTF8编码失败了。而GBK把它分成了('xEE', 'xEE')和('xEE', 'x7F'),而('xEE', 'x7F')导致了GBK编码的失败。

原文地址:https://www.cnblogs.com/kind064100611/p/3486771.html