字符编码

来源:互联网 发布:linux内核熵池 编辑:程序博客网 时间:2024/04/30 21:16

乱码

一个网页或一篇文档出现乱码,对于我们来说应该不陌生。关于乱码的理解对我来说就是无法阅读或理解其正确的意思,来看看乱码吧!

一个简单的HTML文件:

<html><meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" /><head><title>Character Set</title></head><body><center><h1>我是谁</h1></center></body></html>
在你熟悉的文本编辑器中输入上述代码并以“unicode(UTF-8)”编码格式进行保存,通过浏览器查看该文件,出现乱码了吗?疑问

对上面代码中“<meta...”开始的行进行修改:

<meta http-equiv="Content-Type" content="text/html; charset=gb2312" />

以相同的编码格式保存,刷新浏览器,你能理解所看到内容是什么意思吗?抓狂

再次对上面代码中“<meta...”开始的行进行修改:

<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />

以相同的编码格式保存,刷新浏览器,终于看到想要的结果了!

三次运行的结果依次如下:


名词解释



ASCII - 美国信息交换标准码 (ASCII)

        标准的单字节字符编码方案,用于基于文本的数据。起始于50年代后期,在1967年定案。ASCII 码使用指定的 7 位或 8 位二进制数组合来表示 128 或 256 种可能的字符。标准 ASCII 码使用 7 位二进制数来表示所有的大写和小写字母,数字 0 到 9、标点符号,以及在美式英语中使用的特殊控制字符。

ISO-8859-1

        正式编号为ISO/IEC 8859-1:1998,又称Latin-1或“西欧语言”,是国际标准化组织内ISO/IEC 8859的第一个8位字符集。它以ASCII为基础,在空置的0xA0-0xFF的范围内,加入96个字母及符号,藉以供使用附加符号的拉丁字母语言使用。

GB2312

        GB 2312 或 GB 2312-80 是中国国家标准简体中文字符集,全称《信息交换用汉字编码字符集·基本集》,又称GB0,由中国国家标准总局发布,1981年5月1日实施。GB2312编码通行于中国大陆;新加坡等地也采用此编码。中国大陆几乎所有的中文系统和国际化的软件都支持GB 2312。

       GB2312(1980年)一共收录了7445个字符,包括6763个汉字和682个其它符号。因为GB2312支持的汉字太少,1995年的汉字扩展规范GBK1.0收录了21886个符号,它分为汉字区和图形符号区。汉字区包括21003个字符。2000年的GB18030是取代GBK1.0的正式国家标准。该标准收录了27484个汉字,同时还收录了藏文、蒙文、维吾尔文等主要的少数民族文字。

       从ASCII、GB2312、GBK到GB18030,这些编码方法是向下兼容的,即同一个字符在这些方案中总是有相同的编码,后面的标准支持更多的字符。在这些编码中,英文和中文可以统一地处理。区分中文编码的方法是高字节的最高位不为0。按照程序员的称呼,GB2312、GBK到GB18030都属于双字节字符集 (DBCS)。

Unicode

        Unicode(统一码、万国码、单一码)是一种在计算机上使用的字符编码。它为每种语言中的每个字符设定了统一并且唯一的二进制编码,以满足跨语言、跨平台进行文本转换、处理的要求。

        Unicode也是一种字符编码方法,不过它是由国际组织设计,可以容纳全世界所有语言文字的编码方案。Unicode的学名是"Universal Multiple-Octet Coded Character Set",简称为UCS。UCS可以看作是"Unicode Character Set"的缩写。

       UCS有两种格式:UCS-2和UCS-4。顾名思义,UCS-2就是用两个字节编码,UCS-4就是用4个字节(实际上只用了31位,最高位必须为0)编码。

        上小节提到从ASCII、GB2312、GBK到GB18030的编码方法是向下兼容的。而Unicode只与ASCII兼容(更准确地说,是与ISO-8859-1兼容),与GB码不兼容。例如“我”字的Unicode编码是0x6211,而GB码是0xCED2。

UTF-8

        UCS规定了怎么用多个字节表示各种文字。怎样传输这些编码,是由UTF(UCS Transformation Format)规范规定的,常见的UTF规范包括UTF-8、UTF-16、UTF-32。

        UTF8是以8bits即1Bytes为编码的最基本单位,当然也可以有基于16bits和32bits的形式,分别称为UTF16和UTF32,但目前用得不多,而UTF8则被广泛应用在文件储存和网络传输中。

       UTF-8就是以8位为单元对UCS进行编码。从UCS-2到UTF-8的编码方式如下:

UCS-2编码(16进制)UTF-8 字节流(二进制)0000 - 007F0xxxxxxx0080 - 07FF110xxxxx 10xxxxxx0800 - FFFF1110xxxx 10xxxxxx 10xxxxxx

  例如“我”字的Unicode编码是0x6211。6211在0800-FFFF之间,所以肯定要用3字节模板了:1110xxxx10xxxxxx10xxxxxx。将6211写成二进制是:0110 001000 010001, 用这个比特流依次代替模板中的x,得到:111001101000100010010001,即E6 88 91。


回归问题

上节代码共运行三次,得到三个不同的结果,三次以相同的编码方式进行保存,唯一的区别就是“charset”属性的变化。

HTML文件都是以“Unicode(utf-8)”格式进行保存,所以三次对于“我是谁”的编码均为

    我:0xe6 0x88 0x91

    是:0xe6 0x98 0xaf

    谁:0xe8 0xb0 0x81,共9个字节。

因为在HTML代码中指定了“<meta http-equiv="Content-Type" content="text/html; charset=???" />”元素,则浏览器以charset属性中指定编码方式文件内容进行解析。

    当charset指定为“iso-8859-1”时并解析到“我是谁”时,只能按单字节进行解析并显示,所以我们看到了9个字符。

    当charset指定为“gb2312”时并解析到“我是谁”时,则是按双字节的GB编码进行解析并显示,所以我们看到了4个汉字+1个字符。

    当charset指定为“utf-8”时并解析到“我是谁”时,则是按utf-8编码进行解析并显示,所以我们看到了正确的内容。

原创粉丝点击