在讲解本章节的时候,我们需要了解到一些事情。如果要想做到页面不乱码,要求有如下几个因素。
1、html页面的标签中的值与html文本的编码一致,如果不一致会乱码;
2、浏览器不能自动切换编码;
3、页面为"UTF-8",而mysql数据库查询为gbk,也会导致乱码;mysql可以使用如下命令,来临时设置查询编码
set names utf8
4、数据库在存储数据的时候,编码不一致存储,会导致数据库中的数据显示乱码;
5、jsp页面乱码,需要加上
<%@ page contentType="text/html; charset=utf-8" language="java" pageEncoding="utf-8" %>
,同样文件编码需要和内容编码一致
6、PHP解决乱码,需要添加header("content-type:text/html;charset=utf-8");
同样文件编码需要和内容编码一致
计算机之中,存储为二进制的比特流,我们能够识别到的实体化的字符,存储的为二进制。而这两者需要采用一个转换规则,我们称之为"编码"与"解码"。编码就是将字符转换为bit流,而从bit流转换为字符叫做解码。
1、字符集
字符集是各种文字和符号的总称,包括国家文字、标点符号、图形符号、数字等。字符集(Character set)是多个字符的集合,字符集的种类比较多,每个字符集的字符个数不同,常见的字符集有GBK、GB2312、ASCII、Latin1、ISO-8859-1。很多规范和标准在最初制定的时候,没有意识到这将会是以后全球普适的准则,或出于组织本身利益考虑。
2、字符码点
字符码点(Character encoding)是把字符集中的字符编码为指定集合中的某一个对象(例如比特模式、自然数序列,8位组或电脉冲),以便在计算机中存储和网络通信。一般而言,直接将字符在字符集中的位置,或码点(code point),作为编码后的值,字符集和字符编码是紧密耦合的。
只要是学过编程语言,我想都会对ASCII码有一定对认识。学过JSP和MySQL的同学一定会见过如下两个编码;ISO-8859-1和latin1。那么他们之间有什么关系呢?
ASCII(American Standard Code for Information Interchange,美国信息互换编码)是基于基础拉丁字符的一套电脑编码系统,它主要用于显示现代英语,而其扩展版本EASCII(Extended ASCII)则可以面前显示其他西欧语言。它是先进最通用的单字节编码系统,并等同于国际标准ISO/IEC 646。
ASCII采用7bit来编码,共128个码位,由于计算机1个字符8bit,所以最高位位0,即使0x00-0x7F,其中95个可打印字符(包括常用字母、数字、标点符号),还有33个控制字符。具体信息大家可以看相应的编码表,这里我就不引用来。
那么由于早期编码是由美国人设计的,只支持基础拉丁字符,而计算机发展到欧洲,对欧洲其他不只是使用基础拉丁字符的国家就不够用了。那么就在ASCII码没有使用的第八位使用上,这样就可以表达字符数到256个了,增长了一倍了,这就是所谓到EASCII。EASCII基本解决了整个西欧到字符编码问题。但是对于欧洲其他地区来说,比方说北欧、东欧地区,256个字符依然不够用了,因此积极出现了ISO-8859-1。为了解决256个字符不够用到问题,ISO 8859采用了不再是单个独立的编码规则,而是使用一系列的字符集(共15个组成),分别成为ISO-8859-n(1,2,3,4…16,没有12),其对应字符集对应不同的语法,如ISO-8859-1对应西欧语言,ISO-8859-2对应中欧语言,其中所熟悉的latin1就是ISO-8859-1的别名,它表示整个西欧字符集的范围。ISO-8859-n与ASCII是兼容的,即0x00-0x7f范围与ASCII保持一致。
为了扩充ASCII码,以显示本国语言,不同国家与地区指定了不同的标准,由此产生了GB2312(中文简体)、BIG5(中文繁体)、JIS(日文)等各自的编码标准。
为了满足国内在计算机中使用汉字的需要,中国国家标准总局发布了一系列的汉字字符集国家标准编码,统称国标码(GB码),其中最有影响的是1980年发布的《信息交换汉字编码字符集·基本集》,标准号为GB2312-1980。GB2312通行于我国内地,新加坡等地也采用此编码标准,并且几乎所有的中文系统和国际化软件都支持GB2312。
GB2312是一个简体中文字符集,收录简化汉字及一般字符、序号、数字、拉丁字母、希腊字母、俄文字母、汉语拼音符号、汉语注音符号字符,共7445个图形字符,其中6763个汉字。GB2312对所录字符进行了分区处理,共94个区,从1到94,每个区94位,共94*94=8836个码位,由此,每个字符都能找到其唯一对应的区位和码位,这种方式也成为区位码。各区具体说明如下
GB2312以区位码位基础,对字符采用双字节编码,其中高字节表示区码,低字节表示位码,由于区码和位码范围都在1-94,因此范围同ASCII的编码冲突。例如汉字区位码位7174(十进制),表示位形式71、74,而两个ASCII字符‘GJ’也是71、74,这种冲突就会导致编码的混乱,所以位了解决这个问题,GB2312将区位码均加上0xA0,这样高低字节的第八位都变成了1,进而同ASCII码区分开发。
所以GB2312是兼容ASCII码都一种编码方式。在这些编码里,连数学符号、罗马希腊字符、日文的假名都遍进来了,而且还对本来有都数字、标点、字母都统统重新编码来两个字节长都编码,这就是全角字符,而原来都127以下都那些就叫做半角字符了。
GB2312采用双字节编码,原则上可以有65536个码位,实际只收录了7445个。出于兼容ASCII和节省存储容量考虑。为什么呢?因为你采用统一的双字节编码,老外就不同意了,我本来一个字节就能存储和传输的,现在要用两个字节传输,要让你兼容我。于是,GB2312的双字节编码是变长的,有些字符是单字节,有些是双字节,由此代价就是损失一部分码为,除此之外还有一部分空间以作他用;
然而古汉语、人名等方面出现等罕用字,GB2312不能处理,这就导致了后来GBK、GB18030等出现。
在香港、台湾与澳门地区,使用繁体中文字符集,然而GB2312面向简体中文字符集,并不支持繁体汉字,而这些使用繁体中文字符集等地区,一度出现很多不同产商提出的字符集编码,这些编码彼此互不兼容,造成来信息交流的困难,为了统一繁体字符集编码,1984年,台湾五大厂商宏碁、神通、佳佳、零壹以及大众一同指定了一种繁体中文编码方案,即BIG5,又称大五码。
大五码是一种繁体中文汉字字符集,其中繁体汉字13053个,808个标点符号、希腊字母以及特殊符号。大五码采用双字节编码,第一字节范围0x81-0xfe,避开ASCII码的冲突,第二个字节0x40-0x7E和0xA1-0xFE。因此Big5的字符编码同GB2312存储冲突,所以二者不兼容。
编码范围 | 符号类别 |
---|---|
8140-A0FE | 保留 (用作造字区) |
A140-A3BF | 标点符号、希腊字母、特殊符号 |
A3C0-A3FE | 保留 (未开放用于造字区) |
A440-C67E | 常用汉字(先按笔划,再按部首排序) |
C6A1-C8FE | 保留(用作造字区) |
C940-F9D5 | 非常用汉字(先按笔划,再按部首排序) |
8140-A0fe | 保留(用作造字区) |
Big5编码推出后,的到繁体中文软件厂商广泛支持,在使用繁体汉字地区迅速普及使用。目前,Big5编码在台湾、香港、澳门、其他海外华人中普遍使用,成为繁体中文编码的事实标准。在互联网中检索繁体中文网站,所打开的网页中,大多都是通过Big5编码。
GBK为汉字内码扩展规范,K为扩展的声母,英文Chinese Internal Code Specification。GBK编码标准兼容GB2312,是对GB2312-1980的扩展,简、繁体融于一库。GBK采用双字节表示,总体编码范围为8140-FEFE。GBK兼容ASCII。
GB18030全称GB18030-2000《信息交换用汉字编码字符集基本集的扩充》,是我国于2000年3月17日发布的新的汉字编码国家标准,2001年31日后在中国市场上发布的软件必须符合本标准。
GB18030字符集标准解决了汉字、日文假名、朝鲜语和中国少数名字汉字组成的大字符集计算机编码问题。该标准字符总编码空间超过150万个编码位,收录27484个汉字,覆盖中文、日文、朝鲜语和中国少数民族文字。满足中国大陆、香港、台湾、日本和韩国等东亚地区信息交换多文种、大字量、多用途、统一编码格式对要求。
GB18030采用单字节、双字节和四字节三种方式对字符编码,兼容ASCII、GB2312和GBk。
虽然通过使用不同对字符集,我们可以在一台机器上查阅不同语法对文档,但是我们依然无法解决一个问题:在一份文档中显示世界上所有字符。为了解决这个问题,我们需要一个全人类达成共识对巨大对字符集,这就是Unicode字符集。
Unicode(万国码、国际码、统一码、单一码)是计算机科学领域里对一项业界标准。她对于世界上大部分对文字系统进行里整理,编码,使得电脑可以用更为简单对方式来呈现和处理文字。Unicode至今仍在不断增修,每个新版本都加入更多新的字符。Unicode发展由非营利机构统一码联盟(The Unicode Consortium)负责,该机构致力于让Unicode方案取代既有都字符编码方案。Unicode备受认可,并备受认可,并广泛应用于电脑软件都国际化于本地化过程。
Unicode字符集包含来可能出现都所有字符,每个字符对应一个数字,这个数字即码点(Code Point)。
Unicode的编码方案又叫做Unicode转换格式,简称为UTF(Unicode Transformation Format),包括UTF-16、UTF-32以及UTF-8,其中又属于UTF-8使用最为广泛。
UTF-16对应UCS-2,采用双字节编码BMP内位于U+0000支U+D7FF以及U+E000至U+FFFF字符,编码后的值赌赢的码点,由于BMP内的U+D800至U+DFFF码位不对应任何字符, UTF-16借助这些码位,根据一定的规则采用四字节编码辅助平面内U+10000至U+10FFFF的字符,因此, UTF-16是一种变长编码方式。
UTF-16编码分大端序(Big-Endian,简称 UTF-16 BE)和小端序(Little-Endian,简称 UTF-16 LE)两种,区别在于字节序不同。那么我们如果收到 UTF-16字节流“594E”,如何区分是奎字还是乙字呢? UTF-16采用BOM(Byte Order Mark,字节序标记)机制来解决这个问题,在Unicode中有两个特殊字符,一个是U+FEFF,表示"ZERO WIDTH NO-BREAK SPACE";另一个是U+FFFE,它在Unicode中是不存在 的字符,所以不应该出现在实际传输 中, UTF-16在传输字节流前,先传输一个BOM,这样接收者接收到FEFF,就表示这个字节是Big-Endian;如果收到FFFE,就表明这个字节流是Little-Endian的;
UTF-32对应UCS-4,采用四个字节编码所有的Unicode字符。
1、UTF-8编码介绍
UTF-8是一种针对Unicode的可变长度字符编码,也是一种前缀码。它可以用来表示Unicode标准中的任何字符,且其编码中的第一个字符仍于ASCII兼容,这使得ASCII字符的软件无需或只需做少部分修改,即可继续使用,因此它逐渐成为电子邮件、网页及其他存储或发送文字的应用优先采用的编码。
UTF-8使用一至六个自己为每个字符编码(尽管如此,2003年UTF-8被RFC3629重新规范,只能使用原来Unicode定义的区域,U+0000到U+10FFFF,也就是说最多四个字节);
2、UTF-8的优点:
ASCII码是UTF-8的子集,因为一个纯ASCII字符串也是一个合法的UTF-8字符串,所以现存的ASCII文本不需要转换。
UTF-8字符串可以由一个简单的算法可靠识别出来
3、UTF-8的缺点:
与其他Unicode编码相比,特别是UTF-16,在UTF-8中ASCII码占用的空间只有一半,可是在一些字符的UTF-8编码占用的空间要多出1/3,特比是中文、日文和韩文这样的方块文字;
由于在UTF-8编码中,其自身已经带来控制信息,所以不需要BOM机制,但是也可以用BOm来表明编码方式,字符"ZERO WIDTH NO-BREAK SPACE"带UTF-8编码就是0xEFBBBF,所以如果接收者接收到以0xEFBBBF开头到字节流就知道者是UTF-8编码来,但是需要注意,不是所有软件或程序都能够争取处理BOM标记,所以我们不推荐对UTF-8编码对文件加上BOM。
ANSI,美国国家标准协会(American National Standards Institute),在windows系统都编码处理之中,一般采用ANSI来代表系统默认编码方式,而且并不是确定都某一种编码方式——在简体中文操作系统中ANSI编码默认值都是GB系列编码,在繁体中文操作系统中ANSI编码默认指的是BIG5,在日文操作系统中默认置的shift JIS等。