编码编年史
先是ASCII编码,利用一个字节的7位来表示128个字符(大小写字母,数字0到9、标点符号、及在美式英语中利用的分外掌握字符);
表示的字符实在太少,涌现了EASCII,EASCII码比ASCII码扩充出来的128符号包括表格符号、打算符号、希腊字母和分外的拉丁符号;
太小家子气了,中国利用两个字节扩充了ASCII,称之为GB2312,支持汉字6763个和非汉字图形字符682个;
罕用字和繁体字GB2312处理不过来,GBK及GB 18030汉字字符集相继涌现以办理这个问题;
ISO(国际标准化组织)看不下去了,制订了专为办理传统的字符编码方案的局限性的Unicode;
为了节约传输花费和存储空间,UTF-8和UTF-16应运而生;
Base64紧张是为理解决有些系统只能利用ASCII的尴尬,本身比较适宜处理文本数据的传输和存储;
encodeUriComponent:它是将中文、韩文等分外字符转换成utf-8格式的url编码。
ASCII编码
ASCII(American Standard Code for Information Interchange,美国信息交流标准代码)是基于拉丁字母的一套电脑编码系统。它紧张用于显示当代英语,而其扩展版本EASCII则可以部分支持其他西欧措辞,并等同于国际标准ISO/IEC 646。
ASCII第一次以规范标准的型态揭橥是在1967年,末了一次更新则是在1986年,至今为止共定义了128个字符;个中33个字符无法显示(一些终端供应了扩展,使得这些字符可显示为诸如笑脸、扑克牌花式等8-bit符号),且这33个字符多数都已是陈废的掌握字符。掌握字符的用场紧张是用来操控已经处理过的笔墨。在33个字符之外的是95个可显示的字符,包含用键盘敲下空缺键所产生的空缺字符也算1个可显示字符(显示为空缺)。
非ASCII编码
英语用128个符号编码就够了,但是用来表示其他措辞,128个符号是不足的,以是就涌现了很多非ASCII编码。
GB 2312
定义
GB 2312 或 GB 2312–80 是中华公民共和国国家标准简体中笔墨符集,全称《信息交流用汉字编码字符集·基本集》,又称GB0,由中国国家标准总局发布,1981年5月1日履行。GB 2312编码通畅于中国大陆;新加坡等地也采取此编码。中国大陆险些所有的中体裁系和国际化的软件都支持GB 2312。
概述
GB 2312标准共收录6763个汉字,个中一级汉字3755个,二级汉字3008个;同时收录了包括拉丁字母、希腊字母、日文平假名及片假名字母、俄语西里尔字母在内的682个字符。
GB 2312的涌现,基本知足了汉字的打算机处理须要,它所收录的汉字已经覆盖中国大陆99.75%的利用频率。但对付人名、古汉语等方面涌现的罕用字和繁体字,GB 2312不能处理,因此后来GBK及GB 18030汉字字符集相继涌现以办理这些问题。
在利用GB 2312的程序常日采取EUC(EUC全名为Extended Unix Code,是一个利用8位编码来表示字符的方法。)储存方法,以便兼容于ASCII。浏览器编码表上的“GB2312”,常日都是指“EUC-CN”表示法。
分区表示
GB 2312中对所收汉字进行了“分区”处理,每区含有94个汉字/符号。这种表示办法也称为区位码。
01–09区为分外符号。
16–55区为一级汉字,按拼音排序。
56–87区为二级汉字,按部首/笔画排序。
举例来说,“啊”字是GB 2312之中的第一个汉字,它的区位码便是1601。
10–15区及88–94区则未有编码。但在附录3,则在第10区推举作为 GB 1988–80 中的94个图形字符区域(即第3区字符之半形版本)。
字节构造
每个汉字及符号以两个字节来表示。第一个字节称为“高位字节”,第二个字节称为“低位字节”。
“高位字节”利用了0xA1–0xF7(把01–87区的区号加上0xA0),“低位字节”利用了0xA1–0xFE(把01–94加上0xA0)。由于一级汉字从16区起始,汉字区的“高位字节”的范围是0xB0–0xF7,“低位字节”的范围是0xA1–0xFE,占用的码位是7294=6768。个中有5个空位是D7FA–D7FE。
例如“啊”字在大多数程序中,会以两个字节,0xB0(第一个字节)0xA1(第二个字节)储存。(与区位码比拟:0xB0=0xA0+16,0xA1=0xA0+1)。
有两种不同的GB 2312实现
有两种不同的GB 2312实现,在它们之间存在少量的差别,个中至少有一个是缺点的。
字节序实现A实现BA1A4U+00B7 MIDDLE DOTU+30FB KATAKANA MIDDLE DOTA1AAU+2014 EM DASHU+2015 HORIZONTAL BAR实现A与GBK/GB 18030兼容,实现B则不兼容。
在2015年,微软.Net Framework在利用实现A。 iconv-1.14, php-5.6, ActivePerl-5.20, Java 1.7, Python 3.4在利用实现B.[2] Ruby 2.2则同时兼容实现A和实现B,对这几个有冲突的字符,它在内部转换为实现A。
GBK编码
汉字内码扩展规范,称GBK,全名为《汉字内码扩展规范(GBK)》1.0版,由中华公民共和国全国信息技能标准化技能委员会1995年12月1日订定,国家技能监督局标准化司和电子工业部科技与质量监督司1995年12月15日联合以《技能标函[1995]229号》文件的形式公布。
GBK的K为汉语拼音Kuo Zhan(扩展)中“扩”字的声母。英文全称Chinese Internal Code Extension Specification。
GBK 只为“技能规范辅导性文件”,不属于国家标准。国家质量技能监督局于2000年3月17日推出了GB 18030-2000标准,以取代GBK。
Unicode编码
unicode(中文:万国码、国际码、统一码、单一码)是打算机科学领域里的一项业界标准。它对天下上大部分的笔墨系统进行了整理、编码,使得电脑可以用更为大略的办法来呈现和处理笔墨。
Unicode伴随着通用字符集的标准而发展,同时也以书本的形式[1]对外揭橥。Unicode至今仍在不断增修,每个新版本都加入更多新的字符。目前最新的版本为2016年6月21日公布的9.0.0[2],已经收入超过十万个字符(第十万个字符在2005年获采纳)。Unicode涵盖的数据除了视觉上的字形、编码方法、标准的字符编码外,还包含了字符特性,如大小写字母。
Unicode发展由非营利机构统一码同盟卖力,该机构致力于让Unicode方案更换既有的字符编码方案。由于既有的方案每每空间非常有限,亦不适用于多语环境。
Unicode备受认可,并广泛地运用于电脑软件的国际化与本地化过程。有很多新科技,如可扩展置标语言、Java编程措辞以及当代的操作系统,都采取Unicode编码。
须要把稳的是,Unicode只是一个符号集,它只规定了符号的二进制代码,却没有规定这个二进制代码该当如何存储。
比如,汉字“严”的unicode是十六进制数4E25,转换成二进制数足足有15位(100111000100101),也便是说这个符号的表示至少须要2个字节。表示其他更大的符号,可能须要3个字节或者4个字节,乃至更多。
这里就有两个严重的问题,第一个问题是,如何才能差异unicode和ascii?打算机怎么知道三个字节表示一个符号,而不是分别表示三个符号呢?第二个问题是,我们已经知道,英笔墨母只用一个字节表示就够了,如果unicode统一规定,每个符号用三个或四个字节表示,那么每个英笔墨母前都一定有二到三个字节是0,这对付存储来说是极大的摧残浪费蹂躏,文本文件的大小会因此大出二三倍,这是无法接管的。
它们造成的结果是:1)涌现了unicode的多种存储办法,也便是说有许多种不同的二进制格式,可以用来表示unicode。2)unicode在很长一段韶光内无法推广,直到互联网的涌现。
Unicode的实现办法
Unicode的实现办法不同于编码办法。一个字符的Unicode编码是确定的。但是在实际传输过程中,由于不同系统平台的设计不一定同等,以及出于节省空间的目的,对Unicode编码的实现办法有所不同。Unicode的实现办法称为Unicode转换格式(Unicode Transformation Format,简称为UTF)。
UTF-8
互联网的遍及,强烈哀求涌现一种统一的编码办法。UTF-8便是在互联网上利用最广的一种unicode的实现办法。其他实现办法还包括UTF-16和UTF-32,不过在互联网上基本不用。重复一遍,这里的关系是,UTF-8是Unicode的实现办法之一。
UTF-8最大的一个特点,便是它是一种变长的编码办法。它可以利用1~4个字节表示一个符号,根据不同的符号而变革字节长度。
UTF-8的编码规则很大略,只有二条:
1)对付单字节的符号,字节的第一位设为0,后面7位为这个符号的unicode码。因此对付英语字母,UTF-8编码和ASCII码是相同的。
2)对付n字节的符号(n>1),第一个字节的前n位都设为1,第n+1位设为0,后面字节的前两位一律设为10。剩下的没有提及的二进制位,全部为这个符号的unicode码。
下表总结了编码规则,字母x表示可用编码的位。
码点终值字节序列Byte 1Byte 2Byte 3Byte 4Byte 5Byte 6 7U+0000U+007F10xxxxxxx11U+0080U+07FF2110xxxxx10xxxxxx16U+0800U+FFFF31110xxxx10xxxxxx10xxxxxx21U+10000U+1FFFFF411110xxx10xxxxxx10xxxxxx10xxxxxx26U+200000U+3FFFFFF5111110xx10xxxxxx10xxxxxx10xxxxxx10xxxxxx31U+4000000U+7FFFFFFF61111110x10xxxxxx10xxxxxx10xxxxxx10xxxxxx10xxxxxxUnicode 和 UTF-8 之间的转换关系表 ( x 字符表示码点霸占的位 )
UTF-16
UTF-16是Unicode字符编码五层次模型的第三层:字符编码表(Character Encoding Form,也称为 \公众storage format\"大众)的一种实现办法。即把Unicode字符集的抽象码位映射为16位长的整数(即码元)的序列,用于数据存储或通报。Unicode字符的码位,须要1个或者2个16位长的码元来表示,因此这是一个变长表示。
UTF-16比起UTF-8,好处在于大部分字符都以固定长度的字节 (2字节) 储存,但UTF-16却无法兼容于ASCII编码。
UTF-32
UTF-32 (或 UCS-4)是一种将Unicode字符编码的协议,对每一个Unicode码位利用恰好32比特。UTF 只有此一种定长编码。
UTF-32 利用32-比特的码值,只在0到10FFFF的字码空间(百万个码位)。
UTF-32 原来是一个 UCS-4 的子集,于是就现状而言,除了 UTF-32 标准包含额外的 Unicode 意涵,UCS-4 和 UTF-32 大体是相同的。
小端和大端问题
Little endian和Big endian
上一节已经提到,Unicode码可以采取UCS-2格式直接存储。以汉字”严“为例,Unicode码是4E25,须要用两个字节存储,一个字节是4E,另一个字节是25。存储的时候,4E在前,25在后,便是Big endian办法;25在前,4E在后,便是Little endian办法。
这两个古怪的名称来自英国作家斯威夫特的《格列佛游记》。在该书中,小人国里爆发了内战,战役起因是人们辩论,吃鸡蛋时究竟是从大头(Big-Endian)敲开还是从小头(Little-Endian)敲开。为了这件事情,前后爆发了六次战役,一个天子送了命,另一个天子丢了王位。
因此,第一个字节在前,便是”大头办法“(Big endian),第二个字节在前便是”小头办法“(Little endian)。
那么很自然的,就会涌现一个问题:打算机怎么知道某一个文件到底采取哪一种办法编码?
Unicode规范中定义,每一个文件的最前面分别加入一个表示编码顺序的字符,这个字符的名字叫做”零宽度非换行空格“(ZERO WIDTH NO-BREAK SPACE),用FEFF表示。这恰好是两个字节,而且FF比FE大1。
如果一个文本文件的头两个字节是FE FF,就表示该文件采取大头办法;如果头两个字节是FF FE,就表示该文件采取小头办法。
Base64
Base64是一种基于64个可打印字符来表示二进制数据的表示方法。由于2的6次方即是64,以是每6个比特为一个单元,对应某个可打印字符。三个字节有24个比特,对应于4个Base64单元,即3个字节须要用4个可打印字符来表示。
在Base64中的可打印字符包括字母A-Z、a-z、数字0-9,这样共有62个字符,此外两个可打印符号在不同的系统中而不同。
完全的base64定义可见RFC 1421和RFC 2045。编码后的数据比原始数据略长,为原来的4/3。
转换过程:
转换的时候,将三个byte的数据,先后放入一个24bit的缓冲区中,先来的byte占高位。数据不敷3byte的话,于缓冲器中剩下的bit用0补足。然后,每次取出6(由于26=64)个bit,按照其值选择ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/中的字符作为编码后的输出。不断进行,直到全部输入数据转换完成。
当原数据长度不是3的整数倍时, 如果末了剩下一个输入数据,在编码结果后加2个“=”;如果末了剩下两个输入数据,编码结果后加1个“=”;如果没有剩下任何数据,就什么都不要加,这样才可以担保数据还原的精确性。(如果要编码的字节数不能被3整除,末了会多出1个或2个字节,那么可以利用下面的方法进行处理:先利用0字节值在末端补足,使其能够被3整除,然后再进行base64的编码。在编码后的base64文本后加上一个或两个'='号,代表补足的字节数。也便是说,当末了剩余一个八位字节(一个byte)时,末了一个6位的base64字节块有四位是0值,末了附加上两个等号;如果末了剩余两个八位字节(2个byte)时,末了一个6位的base字节块有两位是0值,末了附加一个等号。参考下表:)
Base64编码的浸染
由于某些系统中只能利用ASCII字符。Base64便是用来将非ASCII字符的数据转换成ASCII字符的一种方法。它利用下面表中所利用的字符与编码。
比如:GB2312-根据Base64规则->转换成ASCII码,
吸收端收到ASCII码-根据Base64规则->还原到GB2312
Base64常用于在常日处理文本数据的场合,表示、传输、存储一些二进制数据。包括MIME的email、在XML中存储繁芜数据。而且base64特殊适宜在http,mime协议下快速传输数据。
总结
关于编码和解码一定要对应,否则会产生乱码。