每个程序员都知道,不论是你在手机上看到漂亮小姐姐,还是这篇博文中的文字,在计算机底层存储中都是又一串01编码组成的二进制文件。
虽然对于计算机来说高低电平来控制程序的执行逻辑是很方便的事情,但是人可读不懂复杂冗长的二进制文件,因此就需要制定一种编码规则实现二进制文件与人类文字的相互转换,ACSII码应运而生。
计算机最早是由美国人在使用,于是由他们制定了二进制编码中8bit为一个字节(0~255),划定了0-32的控制码、26个大小写英文字母以及若干个英文符号的二进制编码,将一个字节使用到了127号,因此在ASCII码中一个字节就是一个英文字母,很好计算。美国人将这种编码方式命名为ANSI(AmericanNationalStandardsInstitute,美国国家标准学会)的ASCII码,全称AmericanStartandCodeforInformationInterchange,美国信息互换标准码。
随后很多欧洲国家也开始使用计算机,进而占用了一个字节的剩余128~255的位置,称为ISO8859-1,InternationalOrganizationforStandardization(国际标准组织)。
随后计算机逐渐在中国日本等国家流行开来,和之前面临同样的问题,中国也迫切需要一种编码方式将二进制按照某种规则翻译为汉字显示出来。但是和只有26个的英文字母不同的是,中文的每一个字都是一种新的写法,因此只能对每个汉字映射到一个二进制编码。而常用汉字就有6000多个,之前美国人定义的8bit=1字节完全不够用。于是人们想到了对于ASCII码进行扩展,用两个字节表示。并且将这种编码方式命令为GB2312(GB,Guóbiāo,中华人民共和国国家标准,简称国标,即国标2312)。
计算机在使用这种编码时,判断当前字节是否在0~127(ASCII码范围),如果在,则表示当前为单字节的英文字母;否则,会联合后面的一个字节共同判断当前的汉字表示(注意,在GB2312中两个字节都要大于127)。
整个过程用伪代码表示如下:
细心的读者可以发现,在GB2312标准中,只有两个相邻的字节都是128~255的编码值,才会将其解析为汉字,这其实完全没有必要,会浪费很多数字。因为其实只要读到一个字节是ASCII字符集以外的二进制,也就表明了这是一个汉字,其后的下一个字节完全可以取0~255中的任何一个数字,因此国标2312后又对其进行了字符集的扩展kuòzhǎn,也就诞生了我们耳熟能详的国标扩,GBK,这种双字节表示一个汉字的方式称为DBCS(DoubleByteCharecterSet双字节字符集)。这时候的解析伪代码如下:
台湾海峡隔海相望的另一边,同样使用着汉字的台湾人民也有着一套自己定制的汉字编码规范,称为大五码-BIG5,是繁体中文社区中最常用的编码方式,广泛使用于港澳台地区。
“大五码”(Big5)是由台湾财团法人信息产业策进会为五大中文套装软件所设计的中文共通内码,在1983年12月完成公告,隔年3月,信息产业策进会与台湾13家厂商签定“16位个人电脑套装软件合作开发(BIG-5)项目(五大中文套装软件)”,因为此中文内码是为台湾自行制作开发之“五大中文套装软件”所设计的,所以就称为Big5中文内码。五大中文套装软件虽然并没有如预期的取代国外的套装软件,但随着采用Big5码的国乔中文系统及倚天中文系统先后在台湾市场获得成功,使得Big5码深远地影响繁体中文电脑内码,直至今日。“五大码”的英文名称“Big5”后来被人按英文字序译回中文,以致现在有“五大码”和“大五码”两个中文名称。
说起BIG5编码,笔者就想起小时候刚有家庭PC机的时候,那个时候台湾的单机游戏可以说是百花齐放,当时国内盗版光盘泛滥,笔者当时最爱玩的一款游戏叫做《大富翁》,相信很多玩游戏的读者听到这个名字并不陌生,当时有很多台湾游戏厂商生产的单机游戏是我的童年挚爱。但是唯一的问题就是这该死的编码问题,当时笔者为了玩好某款游戏就不得不装一些字符集插件。否则的话游戏界面就会变成这样。
除了以上两种中文编码方式外,日语中也同样有着汉字,日语的标准编码称为JIS,如JISX0201
日本产业标准(日语:日本産業規格/にほんさんぎょうきかくNihonSangyōKikaku,英语:JapaneseIndustrialStandards,缩写JIS),日语又把JIS音译为ジス,是由日本产业标准调查会(JISC)组织制定和审议。JIS是日本国家级标准中最重要、最权威的标准。
从上面对中文编码的归纳中我们可以看出,随着互联网的逐渐发展,不同地区与文化之间的交流只会越来越紧密,不同编码之间的冲突成为了人与人之间自由交流沟通的阻碍。
为了解决不同地区编码的统一问题(尤其是中文编码问题),美国加州成立了一个Unicode组织,对现存的所有字符都进行了编码设置。
通用字符集(英语:UniversalCharacterSet,UCS)
因为Unicode编码字符集实在太多了,于是人们将Unicode编码进行了分组,分成了若干个平面(plane),我们日常能接触到的中文、英文、日文、韩文等都在0号平面。可以看到,Unicode当前的所有范围为0-0x10FFFF。
Unicode的实现方式称为Unicode转换格式(UnicodeTransformationFormat,简称为UTF)。
试想,如果所有的符号都采用16号平面的三字节存储,那欧美国家的人肯定不答应,因为他们基本不常用非英文字母,一个字节完全可以存储一个字母,现在改用三字节完全是对存储空间和网络传输的浪费。为了解决这个问题,有了如下几种UTF的转换格式:
UTF-32,使用32位即4个字节表示每种字符,例如英文位数不够的就补充0,正如前文所述,这是一种对空间的浪费,一般不会使用。
UTF-16,用2字节表示基本平面(即包含了英文、中文、日文等的0号平面),用4字节表示扩展平面(一般都是甲骨文等奇葩字符),通过特殊的编码位(称为代理)标识当前这2个字节是一个基本平面的字符还是半个扩展平面的字符,对于中文、英文字符都需要用两个字节来存储,只用英文的情况下存在对空间的浪费。
PS:UCS-2编码一般指的是没有执行扩展平面编码的UTF-16,如果你不是要显示甲骨文什么的,UCS-2=UTF-8
在文本文件的开头若干个字节用来标识下当前文件是以上哪种编码类型,该用哪种方式解码。
大端存储:两个字节1234,低位的34放在高位地址中,令人头大小端存储:两个字节1234,低位的34放在低位地址中
urlcode的存在主要是为了应对url中的非法字符,例如url中有特殊含义的保留字符=、/、空格等,还有一些ascii码不支持的字符(如中文)。
因此对于中文来说,所谓的url编码一般情况下其实就是UTF-8编码,如“中文”这两个汉字,UTF-8编码为0xE40xB80xAD0xE60x960x87,经过Url编码之后得到"%E4%B8%AD%E6%96%87",将它放到baidu.com的传参中