PHP与MySQL Web应用平台中文乱码问题研究
2011-10-16朱海岩
朱海岩
(吕梁学院汾阳师范分校,山西 汾阳 032200)
PHP与MySQL Web应用平台中文乱码问题研究
朱海岩
(吕梁学院汾阳师范分校,山西 汾阳 032200)
在运用PHP和MySQL平台进行Web应用程序开发时,经常会在处理中文信息过程中出现乱码.本文就乱码产生的原因进行了深入地分析和讨论,并提出了彻底解决乱码问题的方法.
乱码;字符集;MySQL
PHP和MySQL以其开源、免费、高性能等众多优势,在Web应用领域占领了越来越多的市场份额.现在,PHP与MySQL的主流版本已经能够完全兼容中文信息,但是在进行中文应用程序开发的过程中会经常出现一些乱码问题.究其原因,是因为计算机中汉字的编码方式不统一.同一个汉字在不同字符集中的编码是不一样的,如果一些应用程序默认采用了不同的字符集又缺乏合理的转换机制,在相互通信中就极有可能出现中文乱码.
1 常用包含中文编码的字符集介绍
1.1 GB2312-80
GB2312-80也称GB2312是汉字字符集和编码的代号,是最基本的汉字编码集.中文全称为“信息交换用汉字编码字符集”,1980年,由中华人民共和国国家标准总局发布,1981年5月1日起实施.
GB2312字符集只收录简化汉字,以及常用字母和符号,共收录有7445个字符,其中简化汉字6763个,字母和符号682个.在大陆及海外使用简体中文的地区(如新加坡等)是使用最广泛的中文编码.该标准的制定和应用为规范、推动中文信息化进程起了很大作用,其最大的特点是只支持简体中文.
1.2 GBK
GBK全名为“汉字内码扩展规范”,即GB2312-80的扩展字符集.
1993年,Unicode 1.1版本推出,收录了中国大陆、台湾、日本及韩国通用字符集的汉字,总共有20,902个.随后,中国大陆订定了等同于Unicode 1.1版本的GB 13000.1-93.
由于GB 2312-80只收录了6763个汉字,有不少简体汉字以及台湾和香港地区使用的繁体字,日语及朝鲜语汉字等,并未有收录在内.于是,一些软件开发商利用了GB 2312-80未使用的编码空间,收录了所有出现在Unicode 1.1及GB 13000.1-93之中的汉字,制定了GBK编码.虽然GBK收录了所有Unicode 1.1及GB 13000.1-93之中的汉字,但是编码方式与Unicode 1.1及GB 13000.1-93不同.
1.3 UTF-8
UTF-8(8-bit Unicode Transformation Format)是一种针对Unicode的可变长度字符编码,也是一种前缀码.它可以用来表示Unicode标准中的任何字符,且其编码中的第一个字节仍与ASCII兼容,这使得原来处理ASCII字符的软件无须或只须做少部份修改,即可继续使用.因此,它逐渐成为电子邮件、网页及其他存储或传送文字的应用中,优先采用的编码.
总之,以上几种字符集都能支持中文,但又有所不同.GB2312-80只能支持中文简体,GBK是GB2312-80的超集,支持中文简体、繁体以及日文、韩文符号.UTF-8是一种更通用的字符集,支持世界各种语言的符号.如果某个Web应用程序只是针对国内用户,可以考虑采用GB2312-80字符集,GBK是一种非官方标准的字符集,有时还是会有些问题.如果考虑到该Web应用有可能面对国际用户或者是为了取得更好的兼容性,则应该使用UTF-8字符集.
2 产生乱码的原因分析
2.1 MySQL中与字符集相关的几个系统变量
● character_set_server:服务器字符集,用来为create database命令提供默认值.
● character_set_database:当前数据库的字符集,为create table命令提供默认值.
● character_set_table:当前数据表的字符集,为列的字符集提供默认值.
● character_set_client:客户端默认字符集,当服务器接收到客户端发来的数据时,按些字符集进行解码.
● character_set_results:结果字符集,当服务器向客户端返回查询结果时,以此字符集规则进行编码.
● character_set_connection:连接字符集,这个变量用来决定MySQL怎么处理客户端发来的SQL命令.MySQL会把SQL命令从character_set_client编码转到character_set_connection编码,然后再执行.
2.2 数据流分析
假设客户端(即为PHP页面端)采用UTF-8字符集.
1>客户端向服务器端(即MySQL)发送数据,这些数据根据假设以UTF-8字符集编码.
2>服务器端收到客户端发来的数据,以character_set_client(假设其值为latin1)规定的编码方式进行解码.
3>服务器端处理完客户端的查询请求,准备好数据,以character_set_result(假设其值为latin1)形式编码并发送到客户端.
4>客户端接收到服务器端发来的数据,并以自己的编码形式(第1>步假定为UTF-8)进行解码.
第1>步向服务器发送了一组UTF-8编码的数据,但服务器端以latin1字符集规则进行解码,则不能还原数据,所以存储到数据库中的内容会显示成乱码.
第4>步服务器端向客户端发送了latin1编码形式的数据,但客户端以UTF-8形式解码,则显示在页面上的内容也是乱码.
客户端向服务器端发送正确命令而服务器端不能正确识别也是由于类似原因.
综上所述,产生乱码问题的原因可以总结如表1:
表1
所以,将服务器端的character_set_client、character_set_connection、character_set_results三个系统变量的值设置为客户端所采用的字符集,则可以从根本上解决中文乱码问题.
3 解决乱码问题
3.1 确定客户端的字符集
一般情况下,html的head部分会有如下代码:
此行代码指定了本页面的字符使用UTF-8字符集编码.
如果是纯PHP文件,不包含html代码,也可以使用以下代码指定该页面的字符集:
header(“content-type:text/html;charset=utf-8”);
以上两处代码中的utf-8可以修改成任意合法的字符集.
3.2 修改MySQL的系统变量
1>修改MySQL配置文件
在MySQL的安装目录下找到其配置文件my.ini,分别在 [mysqld]与 [mysql]下添加代码”default-character-set=utf8”.
保存my.ini并重新启动MySQL服务,会发现系统变量的值均被改为utf8.
2>在客户端动态改变MySQL系统变量
由于大多数的用户只是租用虚拟主机运营网站,因此根本无权修改MySQL的配置文件.而且一般情况下程序员也不知道将来代码会放到什么样的服务器环境下运行,因此在客户端与服务器端建立连接以后,动态修改服务器端相关系统变量的值,是一种更通用和可靠的办法.具体代码如下:
4 结论
PHP与MySQL Web应用平台下产生中文乱码的根本原因在于字符集编码方式的不统一.只要约定采用统一的字符集或者控制不同字符集之间正确转换,则可以从根本上解决该平台下的中文乱码问题.
〔1〕Luke Welling、Laura Thomson, 武欣译.PHP 和MySQL Web开发[M].北京:机械工业出版社,2009.
〔2〕姜承尧.MySQL技术内幕:InnoDB存储引擎[M].北京:机械工业出版社,2011.
〔3〕Charles A.Bell,杨涛、王建桥、杨晓云等译.深入理解MySQL[M].北京:人民邮电出版社,2010.
〔4〕W.Jason Gilmori,朱涛江译.PHP 与 MySQL 程序设计[M].北京:人民邮电出版社,2007.
TP391.1
A
1673-260X(2011)08-0036-02