字符编码 (ASCII、ANSI、UNICODE) 的发展
1、ASCII 编码
(American Standard Code for Information Interchange, “美国信息交换标准码),计算机当时只支持英语,字符在计算机中都是以0和1的方式存储的。象a、b、c、d这样的52个字母(包括大写)、以及0、1、2等数字还有一些常用的符号(例如*、#、@等)在计算机中存储时也要使用二进制数来表示,而具体用哪些二进制数字表示哪个符号,就必须要有一定的规则,于是美国有关的标准化组织就出台了所谓的ASCII编码,统一规定了上述常用符号用哪个二进制数来表示。(来自百度百科),ASCII码规定每个字符例如“a”使用1个字节来表示,也就是8为的二进制组合,那么就有00000000-11111111一共256种组合,也就是可以表示256个不同的字符。
- 其中0-31:是控制字符或通讯专用字符(不可以显示的字符,其余为可显示字符),如控制符:LF(换行)、CR(回车)等。
- 32-126:是字符,其中32是空格。
- 48-57为0-9的阿拉伯数字。
- 65-90为26个大写英文字母。
- 97-122为26个小写英文字母。
- 其余的是一些标点符号,运算符号等。
- ASSCII共计有128个,从0到127,也就是从00000000-01111111,最高位都是0。
2、ANSI编码
ASCII只能表示英文字符,那么其他字符怎么表示呢?汉语是这样解决的,用两个ASCII表示一个汉字,而且不用前面的128个。比如汉字“中”在中文操作系统中使用[0xD6,0xD0] 这两个字节存储,这样每个汉字也都有了自己的编码,汉字编码解决了,这就是中国的GB2312编码标准,但是这是中国汉字的编码,那么其他国家呢?其他的国家的计算机操作系统中可能把[0xD6,0xD0] 这两个字节存储成他们的文字,而不是“中”,不同的国家和地区制定了不同的标准,这些使用 2 个字节来代表一个字符的各种文字延伸编码方式,称为 ANSI 编码。
(1)GB2312-80汉字编码
GB2312国标字符集构成一个二维平面,它分成94行、94列,行号称为区号,列号称为位号。每一个汉字或符号在码表中都有各自的位置,字符的位置用它所在的区号(行号)及位号(列号)来表示。每个汉字的区号和位号分别用1个字节来表示,
如:“大”字的区号20,位号83,区位码是20,83
用2个字节表示为:00010100 01010011
问题:信息通信中,汉字的区位码与通信使用的控制码(00H~1FH)发生冲突。
解决方案:为避免汉字区位码与通信控制码冲突,ISO2022规定,每个汉字区号和位号必须分别加上32(即20H),
即区位码加上2020H。
经过这样处理得到的代码称为汉字的“国标交换码”(简称交换码)。因此,“大”字的国际交换码是:
区位码(00010100 01010011)+ 2020H=国际交换码(00110100 01110011)
机内码:
问题:文本中汉字与西文字符经常混用,汉字信息如不予以特别的标识,它与单字节的标准ASCII码就会混淆不清。
解决方法:把一个汉字看作两个扩展ASCII码,使表示GB2312汉字的两个字节的最高位(b7)加“1”,(即27=128=80H)。这种高位为l的双字节(16位)汉字编码就称为GB2312汉字的“机内码”,又称内码。
“大”的国际交换码:(00110100 01110011),内码是:10110100 11110011(B4F3)
3、UNICODE(国际化)
Unicode(又称统一码、万国码、单一码)是计算机科学领域里的一项业界标准,包括字符集、编码方案等。为了使国际间信息交流更加方便,国际组织制定了 UNICODE 字符集,为各种语言中的每一个字符设定了统一并且唯一的数字编号,以满足跨语言、跨平台进行文本转换、处理的要求。Unicode用数字0-0x10FFFF来映射这些字符,最多可以容纳1114112个字符,或者说有1114112个码位。码位就是可以分配给字符的数字。UTF-8、UTF-16、UTF-32都是将数字转换到程序数据的编码方案。
Unicode目前普遍采用的是UCS-2它用两个字节来编码一个字符一般用十六进制来表示UCS-2最多能编码65536个字符
在Unicode中:汉字“字”对应的数字是23383(十进制),十六进制表示为5B57。在Unicode中,我们有很多方式将数字23383表示成程序中的数据,包括:UTF-8、UTF-16、UTF-32。UTF是“Unicode Transformation Format”的缩写,可以翻译成Unicode字符集转换格式,即怎样将Unicode定义的数字转换成程序数据。
例如,“汉字”对应的数字是0x6c49和0x5b57,而编码的程序数据是:
char data_utf8[]={0xE6,0xB1,0x89,0xE5,0xAD,0x97};//UTF-8编码
char16_t data_utf16[]={0x6C49,0x5B57}; //UTF-16编码
char32_t data_utf32[]={0x00006C49,0x00005B57};//UTF-32编码
这里用char、char16_t、char32_t分别表示无符号8位整数,无符号16位整数和无符号32位整数。UTF-8、UTF-16、UTF-32分别以char、char16_t、char32_t作为编码单位。(注: char16_t 和 char32_t 是 C++ 11 标准新增的关键字。如果你的编译器不支持 C++ 11 标准,请改用 unsigned short 和 unsigned long。)“汉字”的UTF-8编码需要6个字节。“汉字”的UTF-16编码需要两个char16_t,大小是4个字节。“汉字”的UTF-32编码需要两个char32_t,大小是8个字节。根据字节序的不同,UTF-16可以被实现为UTF-16LE或UTF-16BE,UTF-32可以被实现为UTF-32LE或UTF-32BE。下面介绍UTF-8、UTF-16、UTF-32、字节序和BOM。
UTF-8
UTF-8以字节为单位对Unicode进行编码。从Unicode到UTF-8的编码方式如下:
Unicode编码(十六进制)
|
UTF-8 字节流(二进制)
|
000000-00007F
|
0xxxxxxx
|
000080-0007FF
|
110xxxxx 10xxxxxx
|
000800-00FFFF
|
1110xxxx 10xxxxxx 10xxxxxx
|
010000-10FFFF
|
11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
|
UTF-8的特点是对不同范围的字符使用不同长度的编码。对于0x00-0x7F之间的字符,UTF-8编码与ASCII编码完全相同。UTF-8编码的最大长度是4个字节。从上表可以看出,4字节模板有21个x,即可以容纳21位二进制数字。Unicode的最大码位0x10FFFF也只有21位。
例1:“汉”字的Unicode编码是0x6C49。0x6C49在0x0800-0xFFFF之间,使用3字节模板:1110xxxx 10xxxxxx 10xxxxxx。将0x6C49写成二进制是:0110 1100 0100 1001, 用这个比特流依次代替模板中的x,得到:11100110 10110001 10001001,即E6 B1 89。
例2:Unicode编码0x20C30在0x010000-0x10FFFF之间,使用4字节模板:11110xxx 10xxxxxx 10xxxxxx 10xxxxxx。将0x20C30写成21位二进制数字(不足21位就在前面补0):0 0010 0000 1100 0011 0000,用这个比特流依次代替模板中的x,得到:11110000 10100000 10110000 10110000,即F0 A0 B0 B0。
创建时间:2020.12.24 更新时间: