2、专题目录
3、*础知识
计算机中存储的信息都是用二补码数表示的;而我们在屏幕上见到的英语、汉字等字符是二补码数转换过后的结果。浅显的说,根据何种规则将字符存贮在计算机中,如'a'用哪些表示,称为"编码";反之,将储存在计算机中的二补码数解析显示下来,称为"解码",就像密码学中的加密和揭秘。在解码过程中,假如使用了错误的解码规则,则造成'a'解析成'b'或则乱码。
字符集(Charset):是一个系统支持的所有具象字符的集合。字符是各类文字和符号的统称,包括各国家文字、标点符号、图形符号、数字等。
字符编码(CharacterEncoding):是一套法则,使用该法则才能对自然语言的字符的一个集合(如字母表或韵母表),与其他东西的一个集合(如号码或电脉冲)进行配对。即在符号集合与数字系统之间构建对应关系,它是信息处理的一项*本技术。一般人们用符号集合(通常情况下就是文字)来抒发信息。而以计算机为*础的信息处理系统则是借助器件(硬件)不同状态的组合来储存和处理信息的。器件不同状态的组合能代表数字系统的数字,因而字符编码就是将符号转换为计算机可以接受的数字系统的数,称为数字代码。
常见字符集名称:ASCII字符集、GB2312字符集、BIG5字符集、GB18030字符集、Unicode字符集等。计算机要确切的处理各类字符集文字,须要进行字符编码,便于计算机就能辨识和储存各类文字。
4、ASCII码
我们晓得,计算机内部,所有信息最终都是一个二补码值。每一个二补码位(bit)有0和1两种状态,因而八个二补码位就可以组合出256种状态,这被称为一个字节(byte)。也就是说linux 安装gbk字符集,一个字节一共可以拿来表示256种不同的状态,每一个状态对应一个符号,就是256个符号,从00000000到11111111。
上个世纪60年代,英国制订了一套字符编码,对日语字符与二补码位之间的关系,作了统一规定。这被称为ASCII码,仍然延用至今。
ASCII码一共规定了128个字符的编码,例如空格SPACE是32(二补码00100000),小写的字母A是65(二补码01000001)。这128个符号(包括32个不能复印下来的控制符号),只占用了一个字节的前面7位,最上面的一位统一规定为0。
▲ASCII编码表
5、非ASCII编码
英文用128个符号编码就够了,并且拿来表示其他语言,128个符号是不够的。例如,在英语中,字母上方有注音符号,它就没法用ASCII码表示。于是,一些美洲国家就决定,借助字节中闲置的最低位编入新的符号。例如,英语中的é的编码为130(二补码10000010)。这样一来,那些美洲国家使用的编码体系,可以表示最多256个符号。
▲扩展ASCII编码表
然而,这儿又出现了新的问题。不同的国家有不同的字母,为此,哪怕它们都使用256个符号的编码方法,代表的字母却不一样。例如,130在英语编码中代表了é,在希伯来语编码中却代表了字母Gimel(ג),在英语编码中又会代表另一个符号。并且不管如何,所有这种编码方法中,0--127表示的符号是一样的,不一样的只是128--255的这一段。
至于欧洲国家的文字,使用的符号就更多了,汉字就多达10万左右。一个字节只能表示256种符号,肯定是不够的,就必须使用多个字节抒发一个符号。例如,繁体英文常见的编码方法是GB2312,使用两个字节表示一个汉字,所以理论上最多可以表示256x256=65536个符号。
英文编码的问题比较复杂,将在文末讨论。这儿先了解下,尽管都是用多个字节表示一个符号,而且GB类的汉字编码与后文的Unicode和UTF-8是毫无关系的。
6、Unicode
正如上一节所说,世界上存在着多种编码方法,同一个二补码数字可以被解释成不同的符号。为此,要想打开一个文本文件,就必须晓得它的编码方法,否则用错误的编码方法剖析,还会出现乱码。为何电子电邮经常出现乱码?就是由于发信人和收信人使用的编码方法不一样。
可以想像,倘若有一种编码,将世界上所有的符号都列入其中。每一个符号都给与一个独一无二的编码,这么乱码问题才会消失。这就是Unicode,如同它的名子所表示的,这是一种所有符号的编码。
Unicode其实是一个很大的集合,如今的规模可以容纳100多万个符号。每位符号的编码都不一样,例如,U+0639表示阿拉伯字母Ain,U+0041表示日语的小写字母A,U+4E25表示汉字严。具体的符号对应表,可以查询,或则专门的汉字对应表。
7、Unicode的问题
须要注意的是,Unicode只是一个符号集,它只规定了符号的二补码代码,却没有规定这个二补码代码应当怎样储存。
例如,汉字严的Unicode是十六补码数4E25,转换成二补码数足足有15位(0101),也就是说,这个符号的表示起码须要2个字节。表示其他更大的符号,可能须要3个字节或则4个字节,甚至更多。
这儿就有两个严重的问题,第一个问题是,怎么能够区别Unicode和ASCII?计算机如何晓得三个字节表示一个符号,而不是分别表示三个符号呢?第二个问题是,我们早已晓得,英语字母只用一个字节表示就够了,若果Unicode统一规定,每位符号用三个或四个字节表示,这么每位英语字母前都必然有二到三个字节是0,这对于储存来说是极大的浪费,文本文件的大小会因而大出二三倍,这是难以接受的。
它们导致的结果是:1)出现了Unicode的多种储存方法,也就是说有许多种不同的二补码格式,可以拿来表示Unicode。2)Unicode在很长一段时间内未能推广,直至互联网的出现。
8、UTF-8
互联网的普及,强烈要求出现一种统一的编码方法。UTF-8就是在互联网上使用最广的一种Unicode的实现方法。其他实现方法还包括UTF-16(字符用两个字节或四个字节表示)和UTF-32(字符用四个字节表示),不过在互联网上*本不用。重复一遍,这儿的关系是,UTF-8是Unicode的实现方法之一。
UTF-8最大的一个特性,就是它是一种变长的编码形式。它可以使用1~4个字节表示一个符号,依据不同的符号而变化字节宽度。
UTF-8的编码规则很简单,只有二条:
下表总结了编码规则,字母x表示可用编码的位:
按照上表,剖析UTF-8编码十分简单。假如一个字节的第一位是0,则这个字节单独就是一个字符;假如第一位是1,则连续有多少个1,就表示当前字符占用多少个字节。
下边,还是以汉字严为例,演示怎么实现UTF-8编码。
严的Unicode是4E25(0101),按照上表,可以发觉4E25处在第三行的范围内(00000800-0000FFFF),因而严的UTF-8编码须要三个字节,即格式是1110xxxx10xxxxxx10xxxxxx。之后,从严的最后一个二补码位开始,依次从后往前填入格式中的x,多出的位补0。这样就得到了,严的UTF-8编码是11,转换成十六补码就是E4B8A5。
9、Unicode与UTF-8之间的转换
通过上一节的事例,可以看见严的Unicode码是4E25,UTF-8编码是E4B8A5,二者是不一样的。它们之间的转换可以通过程序实现。
Windows平台,有一个最简单的转化方式,就是使用外置的记事本小程序notepad.exe。打开文件后,点击文件菜单中的另存为命令,会跳出一个对话框,在最顶部有一个编码的下拉条。
上面有四个选项:ANSI,Unicode,Unicodebigendian和UTF-8
选择完"编码形式"后,点击"保存"按键,文件的编码方法就立即转换好了。
10、Littleendian和Bigendian
上一节早已提及,UCS-2格式可以储存Unicode码(码点不超过0xFFFF)。以汉字严为例,Unicode码是4E25,须要用两个字节储存,一个字节是4E,另一个字节是25。储存的时侯,4E在前,25在后,这就是Bigendian形式;25在前,4E在后,这是Littleendian形式。
这两个奇特的名称来自法国画家斯威夫特的《格列佛散记》。在该书中,小人国里爆发了内乱,战争起因是人们争辩,吃猪肉时到底是从大头(Big-endian)敲开还是从小头(Little-endian)敲开。为了这件事情,前后爆发了六次战争,一个臣子送了命,另一个臣子丢了皇位。
第一个字节在前,就是"大头形式"(Bigendian),第二个字节在前就是"小头形式"(Littleendian)。
这么很自然地,都会出现一个问题:计算机如何晓得某一个文件究竟采用哪一种方法编码?
Unicode规范定义linux vi,每一个文件的最上面分别加入一个表示编码次序的字符,这个字符的名子称作"零宽度非换行空格"(zerowidthno-breakspace),用FEFF表示。这恰好是两个字节,并且FF比FE大1。
假如一个文本文件的头两个字节是FEFF,就表示该文件采用大头形式;倘若头两个字节是FFFE,就表示该文件采用小头形式。
11、实例讲解
下边,举一个实例。
打开"记事本"程序notepad.exe,新建一个文本文件,内容就是一个严字,依次采用ANSI,Unicode,Unicodebigendian和UTF-8编码形式保存。
之后,用文本编辑软件UltraEdit中的"十六补码功能",观察该文件的内部编码方法:
UltraEdit下载地址请至官网:
▲UltraEdit软件
12、最后简略瞧瞧英文字符集和编码
12.1GB系列字符集&编码
计算机发明之处及旁边很长一段时间,只用应用于日本及西方一些发达国家,ASCII才能挺好满足用户的需求。并且当天朝也有了计算机以后,为了显示英文,必须设计一套编码规则用于将汉字转换为计算机可以接受的数字系统的数。
天朝专家把这些127号以后的奇特符号们(即EASCII)取消掉,规定:一个大于127的字符的意义与原先相同,但两个小于127的字符连在一起时,就表示一个汉字,上面的一个字节(他称之为高字节)从0xA1用到0xF7,前面一个字节(低字节)从0xA1到0xFE,这样我们就可以组合出大概7000多个繁体汉字了。在这种编码里,还把物理符号、罗马埃及的字母、日文的假名们都编进去了,连在ASCII里原本就有的数字、标点、字母都统统重新编了两个字节长的编码,这就是常说的"半角"字符,而原先在127号以下的这些就叫"全角"字符了。
上述编码规则就是GB2312。GB2312或GB2312-80是中国国家标准繁体英文字符集,全称《信息交换用汉字编码字符集·*本集》,又称GB0,由中国国家标准总局发布,1981年5月1日施行。GB2312编码通行于中国内地;美国等地也采用此编码。中国内地几乎所有的英文系统和国际化的软件都支持GB2312。GB2312的出现,*本满足了汉字的计算机处理须要,它所收录的汉字早已覆盖中国内地99.75%的使用频度。对于人名、古汉语等方面出现的罕用字,GB2312不能处理,这造成了后来GBK及GB18030汉字字符集的出现。右图是GB2312编码的开始部份(因为其十分庞大,只列出开始部份,具体可查看GB2312繁体英文编码表)。
▲GB2312编码表的开始部份
因为GB2312-80只收录6763个汉字,有不少汉字,如部份在GB2312-80推出之后才简化的汉字(如"啰"),部份人名用字(如中国前首相***的"*"字),香港及台湾使用的简体字,英语及北韩语汉字等,并未有收录在内。于是厂商谷歌借助GB2312-80未使用的编码空间,收录GB13000.1-93全部字符制订了GBK编码。依据谷歌资料,GBK是对GB2312-80的扩充,也就是CP936字码表(CodePage936)的扩充(之前CP936和GB2312-80一模一样),最早实现于Windows95繁体英文版。其实GBK收录GB13000.1-93的全部字符,但编码方法并不相同。GBK自身并非国家标准,只是曾由国家技术监督局标准化司、电子工业部科技与质量监督司公布为"技术规范指导性文件"。原始GB13000仍然未被业界采用,后续国家标准GB18030技术上兼容GBK而非GB13000。
GB18030,全称:国家标准GB18030-2005《信息技术英文编码字符集》,是中华人民共和国现时最新的内码字集,是GB18030-2000《信息技术信息交换用汉字编码字符集*本集的扩展》的修订版。与GB2312-1980完全兼容,与GBK*本兼容,支持GB13000及Unicode的全部统一汉字,共收录汉字70244个。
GB18030主要有以下特性:
▲GB18030编码总体结构
本尺寸的初版使中华人民共和国信息产业部电子工业标准化研究所起草,由国家质量技术监督局于2000年3月17日发布。现行版本为国家质量监督检验总局和中国国家标准化管理委员会于2005年11月8日发布,2006年5月1日施行。此尺寸为在中国境内所有软件产品支持的强制尺寸。
12.2BIG5字符集&编码
Big5,又称为大五码或五大码,是使用简体英文(正体英文)社区中最常用的笔记本汉字字符集标准,共收录13,060个汉字。英文码分为内码及交换码两类,Big5属英文内码,著名的英文交换码有CCCII、CNS11643。Big5虽普及于日本、香港与香港等简体英文通行区,但常年以来并非当地的国家标准,而只是业界标准。倚天英文系统、Windows等主要系统的字符集都是以Big5为*准,但厂商又各自降低不同的造字与造字区,派生成多种不同版本。2003年,Big5被收录到CNS11643英文标准交换码的附表当中,取得了较即将的地位。这个最新版本被称为Big5-2003。
Big5码是一套双字节字符集linux 安装gbk字符集,使用了双八码储存方式,以两个字节来安放一个字。第一个字节称为"低位字节",第二个字节称为"高位字节"。"低位字节"使用了0x81-0xFE,"高位字节"使用了0x40-0x7E,及0xA1-0xFE。
有关Big5的更多技术细节读者可单独深入研究,本文就不赘言了。
13、本文小结
这种字符集和编码的关系很容易让程序员混淆,如今小结一下。
简单来说:Unicode、GBK和Big5码等就是编码的值(也就是术语“字符集”),而UTF-8、UTF-16、UTF32之类就是这个值的表现方式(即术语“编码格式”)。
另外:Unicode、GBK和Big5码等字符集是不兼容的,同一个汉字在这三个字符集里的码值是完全不一样的。如"汉"的Unicode值与gbk就是不一样的,假定Unicode为a040,GBK为b030。以UTF-8为例linux课程,UTF-8码完全只针对Unicode来组织的,假如GBK要转UTF-8必须先转Unicode码,再转UTF-8就OK了。
即GBK、GB2312等与UTF8之间都必须通过Unicode编码能够互相转换:
1)GBK、GB2312--先转-->Unicode--再转-->UTF8
2)UTF8--先转-->Unicode--再转-->GBK、GB2312