计算机信息包括数据信息和控制信息,数据信息又可分为数值、非数值信息。非数值信息和控制信息涵盖字母及各种符号,以二进制的形式存入计算机并得到处理。这种对字母、符号进行编码的二进制代码称为字符编码。
字符编码主要经历了3个阶段:
(1)字符编码产生。字符编码产生的时候,最典型的编码标准是ASCII编码(美国标准信息交换编码),用8位二进制数组合来表示字符。顾名思义,这套编码是美国人编的,所以这套编码包含的字符只需要对美国人够用即可,即这套编码只支持英文字符集。这套编码一共规定了128个字符的编码,包括控制字符、大小写字母、运算符号、标点符号等符号。因此对于这套字符而言,实际上只用了7个bit,最高位统一为0。也称为标准ASCII码、基础ASCII码。后来为这套编码再引入一些外来字母、特殊符号时用到了最高位,这后128个称为扩展ASCII码。
(2)字符编码本地化。不同国家或地区使用的语言不同,用来表达的字符也不同,比如对于中国的汉字而言,使用一套仅包含128个字符的标准ASCII编码显然是不够的,这就导致了不同国家或地区制定自己地区语言的不同标准。典型标准是ANSI编码。ANSI编码是使用2个字节来表示1个字符的各种字符延伸编码方式,对于日本而言,ANSI编码就是JIS编码;简体中文的ANSI编码就是GB2312编码、GBK编码等;繁体中文的ANSI编码就是Big5编码。不同ANSI编码之间互不兼容。
(3)字符编码国际化。为了统一各国、地区的字符编码,国际组织制定了Unicode字符集,为各种语言中的每一个字符设定了统一并且唯一的数字编号。
但是,Unicode字符集只是一个符号集,只规定了符号的二进制代码,没有规定这个代码应该如何存储。
注:UCS(通用字符集)是由ISO制定的标准字符集,其作用和Unicode字符集一样。但是两套同样作用的字符集显得冗余,因此国际对两套字符集进行了整合。
Unicode的实现方式不同于上面说过的编码方式。一个字符的Unicode编码是确定的,但是实际传输过程中,由于不同系统平台设计不一定一致,以及出于节省空间的目的,对Unicode编码的实现方式有所不同。
Unicode编码的实现方式称为UTF(Unicode转换格式),规定了如何对UCS对应的BMP(基本多语种码点)进行传输编码的策略。具体提供了三种策略:UTF-8、UTF-16、UTF-32。
这里具体讲UTF-8:
UTF-8是一种变长编码的标准,其编码序列长度最多可达6个字节。
UTF-8的编码策略是:
~针对不同语言的字符集,使用不同数目的8位二进制元编码成变长的编码字节序列。例如,汉字的编码采用3个字节长度的编码序列。
~第一个8位二进制元中的换码位序列(下列示例中x之前的0/1序列)的特征指明了编码序列中8位二进制元的数目,即首字节中换码位序列为n个值为1的二进制位加上1个值为0的二进制位,此时表示n个字节一组进行编码。后续字节的换码位序列均为“10”。各字节除换码位序列后的剩余二进制位才是编码位。
0xxxxxxx 一个字符的编码等同于ASCII编码。
110xxxxx 10xxxxxx 此时首字节换码位序列为110,有2个1,表示2个字节一组进行编码。
1110xxxx 10xxxxxx 10xxxxxx
11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
UTF-32是一种固定字长编码的标准,始终使用4个字节,足以满足所有Unicode编码的需求,直接存储Unicode的编码方式的二进制代码即可,不需要转换,浪费了空间,提高了效率。
UTF-16是一种既固定又变长的编码标准,使用2个或4个字节存储,这里不多做叙述。
网络中一些应用协议有苛刻的要求,例如SMTP协议,底层邮件协议及邮件网关只能处理7位ASCII编码字符。传送过程中,非ASCII消息中的数据会因为这7位限制遭到拆解。所以若想用邮件传输多媒体信息,就要对非文字信息进行编码,将其转换为7位ASCII格式再传送,这涉及文本化传输编码标准。
文本化传输编码标准主要指以下三种:Base64编码、UTF-7编码、QP编码。
Base64编码是网络上最常见的用于传输8比特字节代码的编码方式之一。
Base64的编码对象可以是任何已编码的数据(例如UTF编码过的)。
编码策略:
~对于要编码对象的最原始二进制数据流,三个字节一组先后放入一个24位的缓冲区中,先放入的字节占高位。
~每次取6位,用此6位的值(0-63)作为索引号,在Base64索引表找到对应的字符。
~用字符的ASCII编码作为编码对象的输出。
~为了保证资料还原的正确性,若最后剩下2个输入数据(无法凑个3个字节一组),在编码结果后加一个“=”;剩下1个则加两个“=”。
~每隔76个字符加上一个回车换行。
Base64编码索引表:
例如编码Man,这3个字符的ASCII编码分别为77、97、110,转化为二进制即:
01001101 01100001 01101110
每6位取为索引,则每个索引号为:19、22、5、46,到索引表中索引得到:TWFu。
UTF-7是一个修改的Base64,主要是将UTF-16的数据用Base64的方法编码为可打印的ASCII字符序列。
编码策略:
~对被编码成UTF-16的ASCII字符,直接使用ASCII等价字节表示(不变)。
~对被编码成UTF-16的非ASCII字符,先通过Base64编码输出后,在前面加上“+”,后面加上“-”。
~可使用非字母表中的字符来表示起止字符。
在Email系统中比较常用,原理是把一个8位的字符用两个十六进制表示,在前面加上“=”。
编码策略:
~对于ASCII字符,不进行转换。
~对于非ASCII字符,将一个8位的字符用两个对应的十六进制数值来表示,在前面加“=”。
~原始数据中的等号“=”用“=3D”表示。
例如字符串“If you believe that truth=beauty, then surely mathematics is the most beautiful branch of philosophy.”,经过QP编码后结果是:
"If you believe that truth=3Dbeauty, then surely=20=
mathematics is the most beautiful branch of philosophy."
QP编码的数据每行长度不能超过76个字符,因此结果的每行末尾加上一个“=”表示软换行,换行符QP编码为“=20”,即每行末尾编码“=20=”。