我们测试过程中经常出现编码方式的一些问题,尤其是电信行业中的短信业务,对接SMPP原生态协议时,经常会有编码方式的转换,所有要了解这些业务,就需要对常见的编码方式有所了解,下面对常见的编码方式进行简单的介绍
ASCII码(American Standard Code for Information Interchange, ASCII):美国标准信息交换代码是由美国国家标准学会(American National Standard Institute , ANSI )制定的,标准的单字节字符编码方案,用于基于文本的数据。它已被国际标准化组织(International Organization for Standardization, ISO)定为国际标准,称为ISO 646标准。适用于所有拉丁文字字母。标准ASCII码也叫基础ASCII码,使用7位二进制数来表示所有的大写和小写字母,数字0到9、标点符号,以及在美式英语中使用的特殊控制字符。(SAG中datacoding=0)
ISO-8859-1(Latin-1):在ASCII基础上有扩展了西欧国家常用的字母符号。即128-255的ASCII字符,就是后来扩展的ISO-8859-1,或者叫Latin-1字符集。后128个称为扩展ASCII码,目前许多基于x86的系统都支持使用扩展(或“高”)ASCII。扩展ASCII码允许将每个字符的第8位用于确定附加的128个特殊符号字符、外来语字母和图形符号。(SAG中datacoding=3)
ISO-8859字符集:因为ASCII字符编码中,没有包括欧洲很多国家所用到的一些扩展的拉丁字母,比如一些重音字母,带音标的等,所以,才设计出新的这个ISO/IEC 8859来支持这些字符。ASCII是7位的单字节编码,其中0x20-0x7E的可见字符。而ISO/IEC 8859,是在ASCII中的普通的可见字符(0x20-0x7E)的基础上,利用了ASCII的7位编码所没有用到的第8位,这样就编码范围就从原先ASCII的0x00-0x7F多扩展出了0x80-0xFF,其中的0xA0-0xFF部分,被ISO/IEC 8859编码所用到。有别于ASCII的单个独立的编码规则,ISO/IEC 8859是一组编码规则的总称,其下包含了共15个字符集,即ISO/IEC 8859-n,其中n=1,...,11,13,...,16
ISO/IEC 8859的字符集,支持很多欧洲的语言,包括丹麦语、荷兰语、德语、意大利语、拉丁语、挪威语、葡萄牙语、西班牙语,瑞典语等。具体如:
ISO8859-1字符集,也就是Latin-1,是西欧常用字符,包括德法两国的字母。
ISO8859-2字符集,也称为Latin-2,收集了东欧字符。
ISO8859-3字符集,也称为Latin-3,收集了南欧字符。
ISO8859-4字符集,也称为Latin-4,收集了北欧字符。
ISO8859-5字符集,也称为Cyrillic,收集了斯拉夫语系字符。
ISO8859-6字符集,也称为Arabic,收集了阿拉伯语系字符。
ISO8859-7字符集,也称为Greek,收集了希腊字符。
Unicode:是在ISO-8859-1基础之上继续扩展的一种多字节的字符编码方法,是由国际组织设计,可以容纳全世界所有语言文字的编码方案。Unicode的学名是“Universal Multiple-Octet Coded Character Set“,简称为UCS。UCS可以看作是“Unicode Character Set“的缩写。UCS规定了怎么用多个字节表示各种文字(即只规定了如何编码,并没有规定如何传输、保存这个编码),常见UCS有两种格式:UCS-2和UCS-4。怎样传输这些编码,是由UTF(UCS Transformation Format)规范规定的,常见的UTF编码方式包括UTF-8、UTF-16、UTF-32。
UTF-16和UTF-32分别是Unicode的16位和32位编码方式。考虑到最初的目的,通常说的Unicode就是指UTF-16。UTF-8就是以8位为单元对UCS进行编码。狭义的说,Unicode就是指UTF-16。
UTF-8:Unicode用一些基本的保留字符制定了三套编码方式。它们分别是UTF-8,UTF-16和UTF-32。正如名字所示,在UTF-8中,字符是以8位序列来编码的,用一个或几个字节来表示一个字符。这种方式的最大好处,是UTF-8保留了ASCII字符的编码做为它的一部分。UTF-8 采用变长度字节来表示字符,理论上最多可以到 6 个字节长度,常见的每个汉字占3个字节,而字母只有1个字节。
UCS-2:UCS有两种格式:UCS-2和UCS-4。顾名思义,UCS-2就是用两个字节编码,UCS-4就是用4个字节(实际上只用了31位,最高位必须为0)编码。我们可以狭义的理解,UCS-2(2个字节)对应的UTF编码为UTF-16;UCS-4(4个字节)对应的UTF编码为UTF-32(不常用)。(即SAG常说的双字节编码,且datacoding=8)
从UCS-2到UTF-8的编码方式如下:
UCS2编码(16进制) | UTF8 字节流(二进制) |
0000 007F (0-127) | 0xxxxxxx |
0080 07FF (128-2047) | 110xxxxx 10xxxxxx |
0800 FFFF (2048-65535) | 1110xxxx 10xxxxxx 10xxxxxx |
例如“汉”字的Unicode编码是6C49(转换成10进展,为27721,在2048-65535之间)。6C49在0800-FFFF之间,所以肯定要用3字节模板了:1110xxxx 10xxxxxx 10xxxxxx。将6C49写成二进制是:0110 110001 001001, 用这个比特流依次代替模板中的x,得到:111001101011000110001001,即E6 B1 89。
同样,UTF-8到Unicode也很简单。还以“汉”字为例。“汉”字的UTF-8编码为E6 B1 89。二进制为11100110 10110001 10001001。从高字节起,取出出现第一个0后的位。我们就得到0110,110001,001001。用两个字节编码就得到了0010,1100,0100,1001,即6C49。
GBK:早期的计算机使用7位的ASCII编码,为了处理汉字,程序员设计了用于简体中文的GB2312和用于繁体中文的big5。GB2312兼容ASCII,但是不兼容ISO-8859-1,也就意味着不能兼容Unicode了。由于GB2312支持的汉字太少。1995年的汉字扩展规范GBK1.0收录了21886个符号。从ASCII、GB2312到GBK,这些编码方法是向下兼容的,即同一个字符在这些方案中总是有相同的编码,后面的标准支持更多的字符。(SAG中datacoding=15)
GSM 7 bit Default Alphabet:这个字符集是短信的专用字符集,大部分短信中心使用的默认字符集就是这个字符集。GSM默认采用7bit编码,实际上,7位编码是种压缩算法,因为,ACII码(不包括扩展ACII),其值小于0X80,最高位bit是0,被忽略了;而7bit编码就利用这一位来存储数据;其编码时,依次将下一7位编码的后几位逐次移至前面,形成新的8位编码。解码时,采用相反的过程进行译码。普通的ASCII码对应的字符只需维护一个7bit映射表即可。(SAG中datacoding=0)
比如:
第一个字节:
8 7 6 5 4 3 2 1
0 a7 a6 a5 a4 a3 a2 a1
第二个字节:
8 7 6 5 4 3 2 1
b1 a7 a6 a5 a4 a3 a2 a1
0 0 b7 b6 b5 b4 b3 b2
第三个字节:
8 7 6 5 4 3 2 1
b1 a7 a6 a5 a4 a3 a2 a1
c2 c1 b7 b6 b5 b4 b3 b2
0 0 0 c7 c6 c5 c4 c3
第四个字节: