Java编码格式介绍(ANSI、GBK、GB2312、UTF-8、GB18030和
UNICODE)
⼀.编码格式介绍
编码⼀直是让新⼿头疼的问题,特别是 GBK、GB2312、UTF-8 这三个⽐较常见的⽹页编码的区别,更是让许多新⼿晕头转向,怎么解释也解释不清楚。但是编码⼜是那么重要,特别在⽹页这⼀块。如果你打出来的不是乱码,⽽⽹页中出现了乱码,绝⼤部分原因就出在了编码上了。此外除了乱码之外,还会出现⼀些其他问题(例如:IE6 的 CSS 加载问题)等等。我写本⽂的⽬的,就是要彻底解释清楚这个编码问题!如果你遇到了类似的问题,那就要仔细的看看这篇⽂章。
ANSI、GBK、GB2312、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。
关于记事本⽆法单独保存“联通”的问题
当你新建⼀个 ⽂本⽂档 之后,在⾥⾯输⼊ “联通” 两个字,然后保存。当你再次打开的时候,原来输⼊的 “联通” 会变成两个乱码。
⽹页编码就是那点事
这个问题就是因为 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 1000
注意到了吗?第⼀⼆个字节、第三四个字节的起始部分的都是”110″和”10″,正好与UTF8规则⾥的两字节模板是⼀致的,于是再次打开记事本 时,记事本就误认为这是⼀个UTF8编码的⽂件,让我们把第⼀个字节的110和第⼆个字节的10去掉,我们就得到了”00001 101010″,再把各位对齐,补上前导的0,就得到了”0000 0000 0110 1010″,不好意思,这是UNICODE的006A,也就是⼩写的字母”j”,⽽之后的两字节⽤UTF8解码之后是0368,这个字符什么也不是。这就 是只有”联通”两个字的⽂件没有办法在记事本⾥正常显⽰的原因。
由这个问题,可以发散出很多问题。⽐较常见的⼀个问题就是:我已经把⽂件保存成了 XX 编码,为什么每次打开,还是原来的 YY 编码?!原因就在于此,你虽然保存成了 XX 编码,但是系统识别的时候,却误识别为了 YY 编码,所以还是显⽰为 YY 编码。为了避免这个问题,微软公司弄出了⼀个叫 BOM 头的东西。
关于⽂件 BOM 头的问题
当使⽤类似 WINDOWS ⾃带的记事本等软件,在保存⼀个以UTF-8编码的⽂件时,会在⽂件开始的地⽅插⼊三个不可见的字符(0xEF
0xBB 0xBF,即BOM)。它是⼀串隐藏的字符,⽤于让记事本等编辑器识别这个⽂件是否以UTF-8编码。这样就可以避免这个问题了。对于⼀般的⽂件,这样并不会产⽣什么⿇烦。
这样做,也有弊处,尤其体现在⽹页中。PHP并不会忽略BOM,所以在读取、包含或者引⽤这些⽂件时,会把BOM作为该⽂件开头正⽂
的⼀部分。根据嵌⼊式语⾔的特点,这串字符将被直接执⾏(显⽰)出来。由此造成即使页⾯的 top padding 设置为0,也⽆法让整个⽹页紧贴浏览器顶部,因为在html⼀开头有这3个字符。如果你在⽹页中,发现了由未知的空⽩等,很有可能就是由于⽂件有 BOM 头造成的。遇到这种问题,把⽂件保存的时候,不要带有 BOM 头!
如何查看和修改某⽂档的编码
1,直接使⽤记事本查看和修改。我们可以⽤记事本打开⽂件,然后点击左上⾓的 “⽂件” =》“另存为”,这时候就会弹出⼀个保存的窗⼝。在下⾯选择好编码之后,点击保存就可以了。
⽹页编码就是那点事
但是这种⽅式的选择余地⾮常⼩,通常⽤来快速查看⽂件是什么编码。我更推荐使⽤下⾯的⽅法。
2,使⽤其他⽂本编辑器(例如:notepad ++)来查看修改。⼏乎所有的成熟的⽂本编辑器(例如:Dreamweaver、Emeditor等),都可以快速查看或修改⽂件编码。这⼀点尤其体现在 notepad++ 上⾯。
打开⼀个⽂件之后,会在右下⾓显⽰当前⽂件的编码。
⽹页编码就是那点事
点击上⾯菜单栏中的 “encoding” 即可把当前⽂档转换成其他编码
⽹页编码就是那点事
IE6 的加载 CSS ⽂件 BUG
当 HTML ⽂件的编码 与想要加载 CSS 的⽂件不⼀致的时候,IE6 将⽆法读取 CSS ⽂件,即 HTML ⽂件没有样式。就本⼈的观察,这个问题从未在其他浏览器中出现过,只在 IE6 中出现过。只需要把 CSS ⽂件,保存成 HTML ⽂件的编码即可。
⼆.windows记事本保存“联通” 编码问题
简单分析:
这是微软记事本的⼀个BUG,准确点就是unicode编码的问题。
只要你拿拼⾳输⼊“liantong”所对应的汉字,⽐如连同,连通等都会出现这个状况。
⽽且这个问题只在第⼀次出现,以后再使⽤就不会有问题了。
记事本默认的保存格式是UTF-8,你若选择保存为Unicode,那么这种状况就不会出现了。
原理分析:
在计算机中字符通常并不是保存为图像,每个字符都是使⽤⼀个编码来表⽰的,⽽每个字符究竟使⽤哪个编码代表,要取决于使⽤哪个字符集(charset)。
在最初的时候,Internet上只有⼀种字符集——ANSI的ASCII字符集,它使⽤7 bits来表⽰⼀个字符,总共表⽰128个字符,其中包括了英⽂字母、数字、标点符号等常⽤字符。之后,⼜进⾏扩展,使⽤8 bits表⽰⼀个字符,可以表⽰256个字符,主要在原来的7 bits字符集的基础上加⼊了⼀些特殊符号例如制表符。
后来,由于各国语⾔的加⼊,ASCII已经不能满⾜信息交流的需要,因此,为了能够表⽰其它国家的⽂字,各国在ASCII的基础上制定了⾃⼰的字符集,这些从ANSI标准派⽣的字符集被习惯的统称为ANSI
字符集,它们正式的名称应该是MBCS(Multi-Byte Chactacter System,即多字节字符系统)。这些派⽣字符集的特点是以ASCII 127 bits为基础,兼容ASCII 127,他们使⽤⼤于128的编码作为⼀个Leading Byte,紧跟在Leading Byte后的第⼆(甚⾄第三)个字符与Leading Byte⼀起作为实际的编码。这样的字符集有很多,我们常见的GB-2312就是其中之⼀。
例如在GB-2312字符集中,“连通”的编码为C1 AC CD A8,其中C1和CD就是Leading Byte。前127个编码为标准ASCII保留,例
如“0”的编码是30H(30H表⽰⼗六进制的30)。软件在读取时,如果看到30H,知道它⼩于128就是标准ASCII,表⽰“0”,看到
C1⼤于128就知道它后⾯有⼀个另外的编码,因此C1 AC⼀同构成⼀个整个的编码,在GB-2312字符集中表⽰“连”。
由于每种语⾔都制定了⾃⼰的字符集,导致最后存在的各种字符集实在太多,在国际交流中要经常转换字符集⾮常不便。因此,提出了Unicode字符集,它固定使⽤16 bits(两个字节、⼀个字)来表⽰⼀个字符,共可以表⽰65536个字符。将世界上⼏乎所有语⾔的常⽤字符收录其中,⽅便了信息交流。标准的Unicode称为UTF-16。后来为了双字节的Unicode能够在现存的处理单字节的系统上正确传输,出现了UTF-8,使⽤类似MBCS的⽅式对Unicode进⾏编码。注意UTF-8是编码,它属于Unicode
字符集。Unicode字符集有多种编码形式,⽽ASCII只有⼀种,⼤多数MBCS(包括GB-2312)也只有⼀种。
例如“连通”两个字的Unicode标准编码UTF-16 (big endian)为:DE 8F 1A 90
⽽其UTF-8编码为:E8 BF 9E E9 80 9A
最后,当⼀个软件打开⼀个⽂本时,它要做的第⼀件事是决定这个⽂本究竟是使⽤哪种字符集的哪种编码保存的。软件有三种途径来决定⽂本的字符集和编码:
unicode汉字最标准的途径是检测⽂本最开头的⼏个字节,如下表:
开头字节
Charset/encoding
EF BB BF
UTF-8
FE FF
UTF-16/UCS-2, little endian
FF FE
UTF-16/UCS-2, big endian
FF FE 00 00
UTF-32/UCS-4, little endian.
00 00 FE FF
UTF-32/UCS-4, big-endian.
例如插⼊标记后,连通”两个字的UTF-16 (big endian)和UTF-8码分别为:
FF FE DE 8F 1A 90
EF BB BF E8 BF 9E E9 80 9A
但是MBCS⽂本没有这些位于开头的字符集标记,更不幸的是,⼀些早期的和⼀些设计不良的软件在
保存Unicode⽂本时不插⼊这些位于开头的字符集标记。因此,软件不能依赖于这种途径。这时,软件可以采取⼀种⽐较安全的⽅式来决定字符集及其编码,那就是弹出⼀个对话框来请⽰⽤户,例如将那个“连通”⽂件拖到MS Word中,Word就会弹出⼀个对话框。
如果软件不想⿇烦⽤户,或者它不⽅便向⽤户请⽰,那它只能采取⾃⼰“猜”的⽅法,软件可以根据整个⽂本的特征来猜测它可能属于哪个charset,这就很可能不准了。使⽤记事本打开那个“连通”⽂件就属于这种情况。
我们可以证明这⼀点:在记事本中键⼊“连通”后,选择“另存为”,会看到最后⼀个下拉框中显⽰有“ANSI”,这时保存。当再当打
开“连通”⽂件出现乱码后,再点击“⽂件”->“另存为”,会看到最后⼀个下拉框中显⽰有“UTF-8”,这说明记事本认为当前打开的这个⽂本是⼀个UTF-8编码的⽂本。⽽我们刚才保存时是⽤ANSI字符集保存的。这说明,记事本猜测了“连通”⽂件的字符集,认为它更像⼀个UTF-8编码⽂本。这是因为“连通”两个字的GB-2312编码看起来更像UTF-8编码导致的,这是⼀个巧合,不是所有⽂字都这样。可以使⽤记事本的打开功能,在打开“连通”⽂件时在最后⼀个下拉框中选择ANSI,就能正常显⽰了。反过来,如果之前保存时保存为UTF-8编码,则直接打开也不会出现问题。
如果将“连通”⽂件放⼊MS Word中,Word也会认为它是⼀个UTF-8编码的⽂件,但它不能确定,因此
会弹出⼀个对话框询问⽤户,这时选择“简体中⽂(GB2312)”,就能正常打开了。记事本在这⼀点上做得⽐较简化罢了。

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。