字符编码:GBK、GB2312、UTF-8
⼀、各编码间的区别
UTF-8:Unicode TransformationFormat-8bit,允许含BOM,但通常不含BOM。是⽤以解决国际上字符的⼀种多字节编码,它对英⽂使⽤8位(即⼀个字节),中⽂使⽤24为(三个字节)来编码。UTF-8包含全世界所有国家需要⽤到的字符,是国际编码,通⽤性强。UTF-8编码的⽂字可以在各国⽀持UTF8字符集的浏览器上显⽰。如,如果是UTF8编码,则在外国⼈的英⽂IE上也能显⽰中⽂,他们⽆需下载IE的中⽂语⾔⽀持包。
GBK是国家标准GB2312基础上扩容后兼容GB2312的标准。GBK的⽂字编码是⽤双字节来表⽰的,即不论中、英⽂字符均使⽤双字节来表⽰,为了区分中⽂,将其最⾼位都设定成1。GBK包含全部中⽂字符,是国家编码,通⽤性⽐UTF8差,不过UTF8占⽤的数据库⽐GBK⼤。
GBK、GB2312等与UTF8之间都必须通过Unicode编码才能相互转换:
GBK、GB2312<===>Unicode<===>UTF8
对于⼀个⽹站、论坛来说,如果英⽂字符较多,则建议使⽤UTF-8节省空间。不过现在很多论坛的插件⼀般只⽀持GBK。
简单来说,unicode、gbk和⼤五码就是编码的值,⽽utf-8、uft-16之类就是这个值的表现形式。⽽前⾯那三种编码是不兼容的,同⼀个汉字,那三个码值是完全不⼀样的。如"汉"的uncode值与gbk就是不⼀样的,假设unicode为a040、gbk为b030,⽽uft-8码,就是把那个值表现的形式。utf-8码完全只针对uncode来组织的,如果gbk要转urf-8必须先转uncode码,再转utf-8就OK了。
需要注意的是,Unicode只是⼀个符号集,它只规定了符号的⼆进制代码,却没有规定这个⼆进制代码应该如何存储,互联⽹的普及,强烈要求出现⼀种统⼀的编码⽅式。UTF-8就是在互联⽹上使⽤最⼴的⼀种unicode的实现⽅式。其他实现⽅式还包括UTF-16和UTF-32,不过在互联⽹上基本不⽤。重复⼀遍,这⾥的关系是,UTF-8是Unicode的实现⽅式之⼀。
⼆、⽹页编码就是那点事
1、ANSI、GBK、GB231
2、UTF-8、GB18030和 UNICODE
这⼏个编码关键词是⽐较常见的,虽然我把我们放在了⼀起说,但并不意味这这⼏个东西是平级的关系。本部分的内容,引⽤⾃⽹络略有修改,不知原⽂出处,故⽆法署名。
很久很久以前,有⼀⼈,他们决定⽤8个可以开合的晶体管来组合成不同的状态,以表⽰世界上的万
物,他们把这称为”字节”。再后来,他们⼜做了⼀些可以处理这些字节的机器,机器开动了,可以⽤字节来组合出很多状态,状态开始变来变去,他们就把这机器称为”计算机”。
开始计算机只在美国⽤。⼋位的字节⼀共可以组合出256(2的8次⽅)种不同的状态。他们把其中的编号从0开始的32种状态分别规定了特殊的⽤途,⼀但终端、打印机遇上约定好的这些字节被传过来时,就要做⼀些约定的动作。遇上 00×10, 终端就换⾏,遇上0×07, 终端就向⼈们嘟嘟叫,例好遇上0x1b, 打印机就打印反⽩的字,或者终端就⽤彩⾊显⽰字母。他们看到这样很好,于是就把这些0×20以下的字节状态称为”控制码”。
他们⼜把所有的空格、标点符号、数字、⼤⼩写字母分别⽤连续的字节状态表⽰,⼀直编到了第127号,这样计算机就可以⽤不同字节来存储英语的⽂字了。⼤家看到这样,都感觉很好,于是⼤家都把这个⽅案叫做 ANSI 的”Ascii”编码(American Standard Code for Information Interchange,美国信息互换标准代码)。当时世界上所有的计算机都⽤同样的ASCII⽅案来保存英⽂⽂字。
后来计算机发展越来越⼴泛,世界各国为了可以在计算机保存他们的⽂字,他们决定采⽤127号之后的空位来表⽰这些新的字母、符号,还加⼊了很多画表格时需要⽤下到的横线、竖线、交叉等形状,⼀直把序号编到了最后⼀个状态255。从128到255这⼀页的字符集被称”扩展字符集”。但是原有的编号⽅法,已经再也放不下更多的编码。
等中国⼈们得到计算机时,已经没有可以利⽤的字节状态来表⽰汉字,况且有6000多个常⽤汉字需要保存呢。于是国⼈就⾃主研发,把那些127号之后的奇异符号们直接取消掉。规定:⼀个⼩于127的字符的意义与原来相同,但两个⼤于127的字符连在⼀起时,就表⽰⼀个汉字,前⾯的⼀个字节(他称之为⾼字节)从0xA1⽤到 0xF7,后⾯⼀个字节(低字节)从0xA1到0xFE,这样我们就可以组合出⼤约7000多个简体汉字了。在这些编码⾥,我们还把数学符号、罗马希腊的字母、⽇⽂的假名们都编进去了,连在 ASCII ⾥本来就有的数字、标点、字母都统统重新编了两个字节长的编码,这就是常说的”全⾓”字符,⽽原来在127号以下的那些就叫”半⾓”字符了。
中国⼈民看到这样很不错,于是就把这种汉字⽅案叫做 “GB2312″。GB2312 是对 ASCII 的中⽂扩展。
但是中国的汉字太多了,后来还是不够⽤,于是⼲脆不再要求低字节⼀定是127号之后的内码,只要第⼀个字节是⼤于127就固定表⽰这是⼀个汉字的开始,不管后⾯跟的是不是扩展字符集⾥的内容。结果扩展之后的编码⽅案被称为 GBK 标准,GBK 包括了 GB2312 的所有内容,同时⼜增加了近20000个新的汉字(包括繁体字)和符号。后来少数民族也要⽤电脑了,于是我们再扩展,⼜加了⼏千个新的少数民族的字,GBK 扩成了 GB18030。从此之后,中华民族的⽂化就可以在计算机时代中传承了。
因为当时各个国家都像中国这样搞出⼀套⾃⼰的编码标准,结果互相之间谁也不懂谁的编码,谁也不
⽀持别⼈的编码。当时的中国⼈想让电脑显⽰汉字,就必须装上⼀个”汉字系统”,专门⽤来处理汉字的显⽰、输⼊的问题,装错了字符系统,显⽰就会乱了套。这怎么办?就在这时,⼀个叫 ISO (国际标谁化组织)的国际组织决定着⼿解决这个问题。他们采⽤的⽅法很简单:废了所有的地区性编码⽅案,重新搞⼀个包括了地球上所有⽂化、所有字母和符号的编码!他们打算叫它”Universal Multiple-Octet Coded Character Set”,简称UCS, 俗
称“UNICODE”。
UNICODE 开始制订时,计算机的存储器容量极⼤地发展了,空间再也不成为问题了。于是 ISO 就直接规定必须⽤两个字节,也就是16位来统⼀表⽰所有的字符,对于 ascii ⾥的那些”半⾓”字符,UNICODE 包持其原编码不变,只是将其长度由原来的8位扩展为16位,⽽其他⽂化和语⾔的字符则全部重新统⼀编码。由于”半⾓”英⽂符号只需要⽤到低8位,所以其⾼ 8位永远是0,因此这种⼤⽓的⽅案在保存英⽂⽂本时会多浪费⼀倍的空间。
但是,UNICODE 在制订时没有考虑与任何⼀种现有的编码⽅案保持兼容,这使得 GBK 与 UNICODE 在汉字的内码编排上完全是不⼀样的,没有⼀种简单的算术⽅法可以把⽂本内容从UNICODE编码和另⼀种编码进⾏转换,这种转换必须通过查表来进⾏。UNICODE 是⽤两个字节来表⽰为⼀个字符,他总共可以组合出65535不同的字符,这⼤概已经可以覆盖世界上所有⽂化的符号。
UNICODE 来到时,⼀起到来的还有计算机⽹络的兴起,UNICODE 如何在⽹络上传输也是⼀个必须考虑的问题,于是⾯向传输的众
多UTF(UCS Transfer Format)标准出现了,顾名思义,UTF8 就是每次8个位传输数据,⽽ UTF16 就是每次16个位,只不过为了传输时的可靠性,从UNICODE到 UTF时并不是直接的对应,⽽是要过⼀些算法和规则来转换。
看完这些,相信你对于这⼏个编码关系等,了解的⽐较清楚了吧。我再来简单的总结⼀下:
中国⼈民通过对 ASCII 编码的中⽂扩充改造,产⽣了 GB2312 编码,可以表⽰6000多个常⽤汉字。
汉字实在是太多了,包括繁体和各种字符,于是产⽣了 GBK 编码,它包括了 GB2312 中的编码,同时扩充了很多。
中国是个多民族国家,各个民族⼏乎都有⾃⼰独⽴的语⾔系统,为了表⽰那些字符,继续把 GBK 编码扩充为 GB18030 编码。
每个国家都像中国⼀样,把⾃⼰的语⾔编码,于是出现了各种各样的编码,如果你不安装相应的编码,就⽆法解释相应编码想表达的内容。
终于,有个叫 ISO 的组织看不下去了。他们⼀起创造了⼀种编码 UNICODE ,这种编码⾮常⼤,⼤到可以容纳世界上任何⼀个⽂字和标志。所以只要电脑上有 UNICODE 这种编码系统,⽆论是全球哪种⽂字,只需要保存⽂件的时候,保存成 UNICODE 编码就可以被其他电脑正常解释。
UNICODE 在⽹络传输中,出现了两个标准 UTF-8 和 UTF-16,分别每次传输 8个位和 16个位。
于是就会有⼈产⽣疑问,UTF-8 既然能保存那么多⽂字、符号,为什么国内还有这么多使⽤ GBK 等编码的⼈?因为 UTF-8 等编码体积⽐较⼤,占电脑空间⽐较多,如果⾯向的使⽤⼈绝⼤部分都是中国⼈,⽤ GBK 等编码也可以。但是⽬前的电脑来看,硬盘都是⽩菜价,电脑性能也已经⾜够⽆视这点性能的消耗了。所以推荐所有的⽹页使⽤统⼀编码:UTF-8。
2、关于记事本⽆法单独保存“联通”的问题
当你新建⼀个⽂本⽂档之后,在⾥⾯输⼊ “联通” 两个字,然后保存。当你再次打开的时候,原来输⼊的 “联通” 会变成两个乱码。
这个问题就是因为 GB2312 编码与 UTF8 编码产⽣了编码冲撞造成的。从⽹上引来⼀段从UNICODE到UTF8的转换规则:
UTF-8
0000 – 007F
0xxxxxxx
0080 – 07FF
110xxxxx 10xxxxxx
0800 – FFFF
1110xxxx 10xxxxxx 10xxxxxx
例如”汉”字的Unicode编码是6C49。6C49在0800-FFFF之间,所以要⽤3字节模板:1110xxxx 10xxxxxx 10xxxxxx。将6C49写成⼆进制是:0110 1100 0100 1001,将这个⽐特流按三字节模板的分段⽅法分为0110 110001 001001,依次代替模板中的x,得到:1110-0110 10-110001 10-001001,即E6 B1 89,这就是其UTF8的编码。
⽽当你新建⼀个⽂本⽂件时,记事本的编码默认是ANSI, 如果你在ANSI的编码输⼊汉字,那么他实际就是GB系列的编码⽅式,在这种编码下,”联通”的内码是:
c1 1100 0001
aa 1010 1010
cd 1100 1101
a8 1010 1000unicode码和ascii码区别
注意到了吗?第⼀⼆个字节、第三四个字节的起始部分的都是”110″和”10″,正好与UTF8规则⾥的两字节模板是⼀致的,于是再次打开记事本时,记事本就误认为这是⼀个UTF8编码的⽂件,让我们把第⼀个字节的110和第⼆个字节的10去掉,我们就得到了”00001 101010″,再把各位对齐,补上前导的0,就得到了”0000 0000 0110 1010″,不好意思,这是UNICODE的006A,也就是⼩写的字母”j”,⽽之后的两字节⽤UTF8解码之后是0368,这个字符什么也不是。这就是只有”联通”两个字的⽂件没有办法在记事本⾥正常显⽰的原因。
由这个问题,可以发散出很多问题。⽐较常见的⼀个问题就是:我已经把⽂件保存成了 XX 编码,为什么每次打开,还是原来的 YY 编码?!原因就在于此,你虽然保存成了 XX 编码,但是系统识别的时候,却误识别为了 YY 编码,所以还是显⽰为 YY 编码。为了避免这个问题,微软公司弄出了⼀个叫BOM 头的东西。
3、关于⽂件 BOM 头的问题
当使⽤类似 WINDOWS ⾃带的记事本等软件,在保存⼀个以UTF-8编码的⽂件时,会在⽂件开始的地⽅插⼊三个不可见的字符(0xEF
0xBB 0xBF,即BOM)。它是⼀串隐藏的字符,⽤于让记事本等编辑器识别这个⽂件是否以UTF-8编码。这样就可以避免这个问题了。对于⼀般的⽂件,这样并不会产⽣什么⿇烦。
这样做,也有弊处,尤其体现在⽹页中。PHP并不会忽略BOM,所以在读取、包含或者引⽤这些⽂件时,会把BOM作为该⽂件开头正⽂的⼀部分。根据嵌⼊式语⾔的特点,这串字符将被直接执⾏(显⽰)出来。由此造成即使页⾯的 top padding 设置为0,也⽆法让整个⽹页紧贴浏览器顶部,因为在html⼀开头有这3个字符。如果你在⽹页中,发现了由未知的空⽩等,很有可能就是由于⽂件有 BOM 头造成的。遇到这种问题,把⽂件保存的时候,不要带有 BOM 头!
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论