APP下载

PHP教学中的乱码问题及解决方法

2018-07-06熊志斌田兴彦

现代计算机 2018年16期
关键词:字符浏览器编码

熊志斌,田兴彦

(海南热带海洋学院艺术与创意学院,三亚 572022)

0 引言

乱码的英文术语是“mojibake”,源于日语,指以非期望的编码格式对文本解码而产生的混乱文字[1]。在PHP教学中,学生经常被乱码所困扰,不能有效应对。一些编程论坛和文献[2-3],虽然罗列了一些乱码的处理方法,但学生往往是知其然而不知其所以然,生搬硬套,有时能解决问题,有时不能解决问题。本文介绍了字符编码的基本知识和Web工作原理,HTTP响应报文格式,动态网页的内容构成,从PHP程序运行过程出发,沿着HTTP请求响应的数据流,分析了在Web服务器和数据库服务器中可能导致乱码的原因及解决办法,以供教学参考。

1 字符集与编码

字符(character)是包括文字、数字、标点符号、图形符号等人类可以理解的各种符号的总称。字符集(character set)是包含一定数量字符的集合。编码字符集(coded character set)是每个字符对应唯一整数编码的字符集,编码字符集中的字符所对应的整数称为码点(code point)。编码字符集常常被简称为字符集,要结合上下文语境来理解。常见字符集有:ASCII字符集、Unicode字符集、UCS字符集、GB2312字符集、GBK字符集,BIG5字符集、GB18030字符集。从码点到二进制字节序列的映射称为编码方案,每种字符集都有一种或几种编码方案。从字符转换成码点,码点按编码方案转换成二进制序列,这个过程称之为编码。从二进制序列按编码方案转换成码点,码点转换成字符,这个过程称之为解码。

最早的字符集编码是美国计算机专家制定的适用英文系统的ASCII码(American Standard Code for Infor⁃mation Interchange,美国信息交换标准代码)。ASCII码包括英文大小写字符、阿拉伯数字、西文符号等可显示字符,以及回车、换行、退格等打印控制符。

中文字符集编码有GB2312字符集、GBK字符集、GB18030字符集、BIG5字符集。字符集GB2312(信息交换用汉字编码字符集·基本集)收录6763个汉字,基本满足汉字的计算机信息处理。GBK字符集是对GB2312字符集的扩展,收录了GB2312字符集之外的生僻字,港澳台地区使用的繁体字,GBK字符集并不是国家颁布的标准,编码由微软制定,最早用于Windows系统。GB18030字符集(信息技术中文编码字符集)是我国最新的中文字符编码标准,与GB2312字符集完全兼容,与GBK字符集基本兼容,总过收录了70244个汉字符号,包括简体汉字,繁体汉字,我国少数民族的字符。BIG5字符集是我国港澳台地区使用的繁体中文字符集,BIG5字符集用两个字节表示一个字符。

由于各国的编码方案可能不兼容,同一个文件在不同国家的信息处理系统会产生乱码,随着互联网的发展,这一弊端日益凸显。为了解决这个问题,非盈利组织机构Unicode联盟(Unicode Consortium)制定了包括世界各国文字的Unicode字符集标准,Unicode字符集上有3种编码方案,分别是UTF-32、UTF-16、UTF-8。UTF-32采用4个字节表示一个字符,UTF-16采用2个字节表示一个字符。UTF-8是一种变长编码,用1到4个字节表示一个字符,UTF-8用3个字节表示一个汉字。同一时期,ISO组织制定了一个涵盖世界各国文字的 UCS(Universal Coded Character Set)字符标准(ISO/IEC 10646)。ISO/IEC 10646标准与Unicode标准定义的字符、字符编码、字符名称是完全相同的,目前二者相互协调发展[4]。这两个组织仍独立地公布自己的标准,Unicode标准已经成为事实上的工业标准。

乱码的根源就在于没有按期望的编码格式进行解码。计算机中的文件都以二进制字节序列形式保存在硬盘上,打开文件需要解码,把二进制序列转换成自然语言中的字符,如果没有按文件保存时的编码格式进行解码,显示出来的就是乱码。例如,文件保存的是UTF-8编码,打开文件的时候按GBK编码格式解码,显示出来的就是乱码。

2 Web工作原理

PHP网站运行环境包括:客户端浏览器、Web服务器和MySQL数据库服务器,其中,Web服务器中包括Apache服务器和PHP预处理器。在Windows中文系统中,浏览器默认编码一般是GBK,也可以通过浏览器的设置功能修改默认编码,MySQL数据库在安装的时候可以指定默认编码,如果没有指定,则服务器默认编码是latin-1。

Apache+MySQL运行环境下的Web工作原理如图1所示:客户端浏览器发送访问某个页面的请求,Web服务器端浏览器发送响应报文,如果是HTML静态页面,Apache服务器返回HTML文件(包含CSS、Java-Script)到客户端浏览器,如果是PHP动态页面文件,PHP解释器执行脚本,如果涉及到访问数据库,查询结果再通过Web服务器以HTML文件返回到客户端浏览器。

图1 Web工作原理

浏览器和Web服务器之间的数据传输协议是HTTP协议,HTTP协议规定了浏览器的请求报文格式和Web服务器的响应报文格式。请求报文由请求行、请求头部和请求正文3部分构成,响应报文由状态行、响应头部和响应正文3部分构成,响应正文也就是页面文件。其中与乱码有关的是响应头部里有一个字段charset,此字段的值是某种编码格式,如UTF-8,该字段的功能是通知浏览器,响应正文(网页文件)的编码格式。浏览器正是按响应报文头部charset的值对网页文件的字节序列解码,渲染成网页。

3 乱码的产生与处理

3.1 Web 服务器导致的乱码

浏览器在接受到响应报文后,按响应头部的字段charset的编码格式对响应正文解码。如果响应报文中字段charset的指定编码格式与网页文件的编码格式不一致,或者字段charset的值为空,而浏览器默认的字符编码与网页文件的编码格式不一致,则浏览器显示乱码。Web服务器没有正确的指定编码格式,有3种处理方式。

(1)Web服务器指定编码

Web服务器响应头部的charset字段值和网页文件编码一致,浏览器就能正常显示网页。charset字段值由Web服务器中Apache和PHP的配置参数决定,在PHP的php.ini文件中有默认的配置参数项:

default_charset="UTF-8"

通过修改此项可以为Web服务器指定其他字符集编码。

在Apache中的httpd.conf配置文件中并没有默认配置参数,用户可以在httpd.conf文件尾部添加:

AddDefaultCharset UTF-8

通过此项为Web服务器指定字符集编码。php.ini文件和httpd.conf文件有各自的字符编码配置参数,但只有一个配置参数在Web服务器生效,php.ini配置参数的优先级高于httpd.conf配置参数。如果php.ini和httpd.conf同时指定了不同的默认字符集,则php.ini中的默认字符集生效。

在php.ini文件或httpd.conf文件配置了字符集编码参数后,Web服务器在发送网页文件时,无论是HT⁃ML文件还是PHP文件,都会把配置文件的默认字符编码作为响应报文头部的charset字段值发送到浏览器。

这种解决方法的本质就是使Web服务器的默认字符编码和网页文件的编码保持一致,因此,在开发PHP程序时,把开发环境的编辑器的字符编码设置成服务器端指定的字符编码就可以了。

(2)网页文件指定编码

如果Web服务器中php.ini和httpd.conf都不指定默认字符集,则响应报文头部的charset字段值为空,Web程序员可以通过网页文件中的代码来控制浏览器的解码,使浏览器按正确的字符编码解析网页文件。HTML文件和PHP文件有不同的控制方式。

对于HTML文件,程序员必须在每一个文件的头部添加meta标签,声明HTML文件的编码格式。如HTML文件本身就是GBK编码,声明方式如下:

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

浏览器接到从Web服务器传来的HTML文件字节序列流时,就会按GBK编码格式进行解码。

对于PHP文件,程序员必须在每一个文件的起始处添加header函数,假如PHP文件本身是GBK编码,声明方式如下:

<?php header("content-type:text/html;charset=GBK")?>

header函数的作用是把括号里面的信息发到Web服务器的响应报文中的响应头部,浏览器按响应头部的字段charset的值来解码PHP文件。

header函数指定字符集编码的优先级高于php.ini,也就是说即使Web服务器端的php.ini文件有字符编码的配置参数,参数对PHP文件不会生效。但是,由于在HTML文件中不能使用header函数,所以php.ini中字符编码的配置参数对HTML文件还是生效的。因此,为了统一处理HTML文件和PHP文件,Web服务器中php.ini文件和httpd.conf文件都不指定默认字符集,这种方式灵活性很大,可以使Web程序员灵活控制每一个网页文件解码。

(3).htaccess文件指定编码

.htaccess文件是Apache服务器支持的基于目录的配置文件,可以放置在站点任何目录下,其功能非常广,包括:用户自动重定向、自定义错误页面、封禁特定IP地址、拒绝访问目录,以及指定字符编码[5]。.htaccess文件的配置参数的优先级高于Web服务器中的php.ini文件和httpd.conf文件中配置参数。在.htaccess文件中加入下列参数,可以指定字符编码:

IndexOptions Charset=utf-8

AddDefaultCharset utf-8

php_value default_charset“utf-8”

其中IndexOptions Charset=utf-8用来设置Apache服务器目录字符编码,AddDefaultCharset UTF-8将覆盖httpd.conf文件中配置参数,php_value default_char⁃set“utf-8”将覆盖php.ini配置参数。将上述参数的第二行第三行的utf-8改成off,则httpd.conf文件和php.ini文件中字符集的配置参数失效,Web服务器响应报文的头部的字段charset的值为空。

写有上述配置参数的.htaccess文件放入某个目录下,Web服务器在发送该目录及子目录下的网页文件时,报文响应头部的字段charset的值就是.htaccess文件指定的编码。这种方式适合于用户无权修改Web服务器配置文件的虚拟主机网站。

3.2 数据库服务器导致的乱码

PHP文件是动态网页,从字节序列的角度考察,网页文件的字节序列可能由两部分构成,一部分是网页文件本身的字节序列,另一部分字节序列是读取数据库中的内容。如果数据库的编码格式与PHP文件的编码格式不一致,造成网页文件这两部分的字节序列编码格式不一致,按网页文件编码格式解码,必然出现乱码。开发PHP程序时,有时会出现网页部分内容正常显示,而在表格中数据库内容乱码的情况,就是PHP文件的编码与数据库的编码不一致造成的。处理数据库服务器造成的乱码有3种方法。

(1)创建数据库指定编码

MySQL数据库服务器支持在创建数据库时指定数据库级的编码格式,所以无论是图形化的向导创建数据库,还是通过执行脚本都可以指定数据库的字符编码。为了避免乱码,创建数据库时,可以根据PHP文件的编码格式,指定数据库的编码,使得数据库和PHP文件的编码格式保持一致。在创建数据库时,不仅可以指定数据库的字符编码,甚至可以指定数据库中某个表,或表中的某列采取特定的编码格式。

(2)程序控制编码

数据库和PHP文件的编码格式不一致时,在DSN字符串里添加charset参数,charset参数的值就是PHP文件的编码。PDO对象在读写数据库时,按指定的字符编码转换。在PHP程序中,DSN字符串变量形式:

$dsn="mysql:host=localhost;dbname=students;charset=utf8";

$db=new PDO($dsn,$user,$password);

无论数据库的编码格式是什么,指定DSN字符串里charset参数的值是稳妥的。有些虚拟主机网站,用户连建库的权限都没有,根本就不可能指定数据库的字符编码,只能采用这种方式。

(3)修改配置参数

MySQL数据库服务器有服务器级和数据库级两个级别的字符集编码和校验规则,其中服务器级的字符集和校验规则是不可缺少的,在安装MySQL服务器时就必须指定字符集编码和校验规则,默认字符集编码是latin-1。在创建数据库时,如果没有指定字符集编码和校验规则,则延用服务器的字符集编码和校验规则。

服务器级字符集编码,可以通过修改配置参数更改默认的字符集编码。在MySQL的安装目录下,有配置文件my.ini,

#SERVER SECTION

#The default character set that will be used when a new schema or table is

#created and no character set is defined

character-set-server=utf8

通过修改参数项character-set-server=utf8可以更改服务器的字符集编码。

某个具体数据库的字符集也可以通过配置文件更改默认的字符集编码,在安装目录下,有个Data文件,找到具体数据库目录,其中有个db.opt配置文件,有类似参数信息:

default-character-set=utf8

default-collation=utf8_general_ci

修改此参数可以更改服务器的字符集编码。

4 结语

网页乱码的根源就在于浏览器没有按网页文件的编码格式解码,处理PHP乱码关键点就在于:一要考察浏览器的编码格式来自服务器指令还是网页文件代码,二要考察PHP文件编码格式与数据库编码格式是否一致,找到问题出在哪个环节,就可以灵活地制定处理策略。在PHP教学中,面对中文乱码的问题,不能简单罗列乱码的处理方法,要从字符编码,从Web工作原理,从HTTP协议的响应报文的格式,分析乱码产生的根源,分析Web应用程序各环节可能产生乱码的地方及对应的处理方法。学生掌握了这些基本原理和基本应对能力后,面对乱码现象,就能根据实际应用的需求,灵活地制定处理方案。

[1]Mojibake[EB/OL].https://en.wikipedia.org/wiki/Mojibake.

[2]曹晖.字符集与字符编码标准[J].西北民族大学学报(自然科学版),2006,27(3):36-42.

[3]张博.基于mysqlphp程序开发的中文乱码问题及对策分析[J].电子制作,2013(4):67-67.

[4]庞天丙.AMP环境下“乱码”问题的解决[J].电脑知识与技术,2011,07(16):3869-3870.

[5]Apache HTTP Server Tutorial:.htaccess Files[EB/OL].http://httpd.apache.org/docs/current/howto/htaccess.html

猜你喜欢

字符浏览器编码
生活中的编码
《全元诗》未编码疑难字考辨十五则
论高级用字阶段汉字系统选择字符的几个原则
子带编码在图像压缩编码中的应用
字符代表几
一种USB接口字符液晶控制器设计
图片轻松变身ASCⅡ艺术画
微软发布新Edge浏览器预览版下载换装Chrome内核
反浏览器指纹追踪
Genome and healthcare