字符编码
中文编码
兼容性(包含)关系:
GB18030兼容GBK,GBK兼容GB2312,GB2312兼容ASCII
ASCII:
ASCII 是目前最简单也是最通用的字符集,每个字符占据1bytes,
用二进制表示的话最高位必须为0(扩展的ASCII不在考虑范围内),因此ASCII只能表示128个字符,包含数字,大小写字母以及常用的英文标点符号。
GB2312:
GB2312是一个字符集,每个字占据2bytes,为了兼容ASCII这2bytes最高位不可以为0。
全称“信息交换用汉字编码字符集”(GB是“国标”的拼音缩写,2312是国标序号),包含6763个汉字以及682个特殊符号。当文本中的字节小于0x80,为ASCII码,而当文本中的字节大于0x80时,此字节加下一个字节共同表示一个汉字。
GBK:
GBK也是一个字符集,是GB2312的扩充(K是“扩”的拼音缩写),包含21003个汉字(包括繁体字)和984个汉语标点符号、部首,兼容GB2312
GB18030 :
GB18030也是一种字符集,兼容GBK,对GBK多出来的汉字使用4bytes编码。
当然,为了兼容GBK,这个四字节的前两位显然不能与GBK冲突,至2005年发布,GB18030编码的中文文件已经有70244个汉字了,包含了少数民族文字。
类别 | 码位范围 | 码位数 | 字符数 | 字符类型 |
双字节部分 |
第一字节 0xB0-0xF7 第二字节 0xA1-0xFE |
6768 | 6763 | 汉字 |
第一字节0x81-0xA0 第二字节0x40-0xFE |
6080 | 6080 | 汉字 | |
第一字节0xAA-0xFE 第二字节0x40-0xA0 |
8160 | 8160 | 汉字 | |
四字节部分 |
第一字节0x81-0x82 第二字节0x30-0x39 第三字节0x81-0xFE 第四字节0x30-0x39 |
6530 | 6530 | CJK统一汉字扩充A |
第一字节0x95-0x98 第二字节0x30-0x39 第三字节0x81-0xFE 第四字节0x30-0x39 |
42711 | 42711 | CJK统一汉字扩充B |
我们通常把GB2312字符集这6763字称为“常用字”
而将包含在GBK而不包含在GB2312字符集内的汉字称为“生僻字”。
GBxxx都是我们国家定义的标准,当然只针对我们国家的汉字以及ASCII等。而unicode的出现是为了解决全球的字符编码。
国际编码
编码格式
=
编码格式
+
存储格式
对于GBxxx是将编码和存储方式整合再一起了,我们叫字符集。
UNICODE:
unicode只是编码,不涉及存储格式
而utf-x是基于unicode编码的编码格式,通常包含utf-8、utf-16、utf-32三种。
对于utf-8、utf-16、utf-32三者都使用unicode编码,但存储格式存在差异,它的字符编码中的每个字节都可以小于0x80
在Unicode 5.0的99089个字符中,有71226个字符与汉字有关。它们的分布如下:
Block名称 | 开始码位 | 结束码位 | 字符数 |
---|---|---|---|
CJK统一汉字 | 4E00 | 9FBB | 20924 |
CJK统一汉字扩充A | 3400 | 4DB5 | 6582 |
CJK统一汉字扩充B | 20000 | 2A6D6 | 42711 |
CJK兼容汉字 | F900 | FA2D | 302 |
CJK兼容汉字 | FA30 | FA6A | 59 |
CJK兼容汉字 | FA70 | FAD9 | 106 |
CJK兼容汉字补充 | 2F800 | 2FA1D | 542 |
GB2312中的6763个汉字在Unicode中不是连续的,分布在CJK统一汉字字符区(0x4E00-0x9FA5)的20902个汉字中
GBK中的21003个汉字包含在CJK统一汉字字符区的20902个汉字,剩余的101个在不同的区域.
UTF8
UTF-8(Unicode Transformation Format 8-bit)编码是一种可变宽度的编码格式,是用以解决兼容国际字符的一种多字节编码。
对于英文字符较多的论坛则用UTF-8节省空间。另外,如果是外国人访问你的GBK网页,需要下载文语言包支持,访问UTF-8编码的网页则不出现这问题,所以现在一般的网页都是使用utf-8编码。
- 1.它是一个变长字节(1~4个字节)的编码方式。
- 2.对于一个字节的编码格式:字节bit[7:0]的bit[7]位必须为0,bit[6:0]这7个位用来编码,即二进制为0b0xxxxxxx。
-
3.对于n字节(2,3,4个字节)的编码格式,用首字节的bit[7:8-n]位置1,bit[8-n-1]置位0表示字节位数。
如首字节为0b110xxxxx表示二字节的编码格式。同理0b1110xxxx为三字节格式。剩下的除首字节剩下的字节的bit[7:6]=0b10.其余位用于编码。如编码0b1110xxxx,0b10xxxxxx,0b10xxxxxx表示一个三字节的编码格式,其中x代表的是可编码的位置,可以计算出三字节编码格式共有2^24个编码位置。
字节数 | utf-8 编码格式 | 编号范围 |
---|---|---|
1 | 0b0xxxxxxx | 0x00~0x7F |
2 | 0b110xxxxx 0b10xxxxxx | 0x80~0x7FF |
3 | 0b1110xxxx 0b10xxxxxx 0b10xxxxxx | 0x800~0xFFFF |
4 | 0b11110xxx 0b10xxxxxx 0b10xxxxxx 0b10xxxxxx | 0x10000~0x10FFFF |
unicode转utf-8步骤:
- 首先找到unicode字符编码所在上表中的编号范围。如字符A的unicode编码为0x41,位于utf-8 1字节编码格式(0~127)的编号范围
-
.将unicode字符编码的二进制位从右到左填入上表中的x位(注意要去掉高位的0)。如字符A(0x41=0b01010001)去掉高位0则为0b1010001。将其填入0b0xxxxxxx后则为0b01010001.也就是utf-8字符A的编码值。
再举个例子:汉字郭的unicode字符编码为0x90ED(0b10010000,11101101),由0x800 < 0x90ED < 0xFFFF得到它的编码格式为utf-8的3字节编码格式。然后将其二进制0b10010000,11101101填入0b1110xxxx 0b10xxxxxx 0b10xxxxxx后为0b11101001,10000011,10101101=0xE983AD.也就是utf-8字符郭的编码值
c++ unicode转utf-8代码:
/*
* utf-8字符编码转化为unicode编码。(2字节模式)
* pIn:要转换的字符串首地址
* charsize:接收返回的utf8字符的字节数(1~3)
* pOut:获取到的UCS2编码,pOut[0]为首字节。
*/
int Utf8ToUCS2(const char *pIn,char *charsize,char *pOut)
{
uint8_t firstValue = *pIn;
char *pUCS2 = pOut;
if(firstValue < 0x80){//0~127 ASCII 1byte
pUCS2[0] = 0;
pUCS2[1] = *pIn;
*charsize = 1;
}
else if( (firstValue & 0xE0) == 0xC0){//128~2047 2byte
if( (pIn[1] & 0xC0) != 0x80){
return -1;
}
pUCS2[0] = (pIn[0] & 0x1F) >> 2;
pUCS2[1] = (pIn[0] << 6) + (pIn[1] & 0x3F);
*charsize = 2;
}
else if( (firstValue & 0xF0) == 0xE0){//2048~65536 3byte
if( (pIn[1] & 0xC0) != 0x80 || (pIn[2] & 0xC0) != 0x80){
return -1;
}
pUCS2[0] = (pIn[0] << 4) + ((pIn[1] & 0x3F) >> 2);
pUCS2[1] = (pIn[1] << 6) + (pIn[2] & 0x3F);
*charsize = 3;
}
else {//>3byte不处理,汉字用不到4字节的编码
*charsize = 0;
return -1;
}
return 0;
}