PHP 中文乱码解决办法总结分析


Posted in PHP onJuly 30, 2009

一.首先是PHP网页的编码
1. php文件本身的编码与网页的编码应匹配
a. 如果欲使用gb2312编码,那么php要输出头:header(“Content-Type: text/html; charset=gb2312″),静态页面添加<meta http-equiv=”Content-Type” content=”text/html; charset=gb2312″>,所有文件的编码格式为ANSI,可用记事本打开,另存为选择编码为ANSI,覆盖源文件。
b. 如果欲使用utf-8编码,那么php要输出头:header(“Content-Type: text/html; charset=utf-8″),静态页面添加<meta http-equiv=”Content-Type” content=”text/html; charset=utf-8″>,所有文件的编码格式为utf-8。保存为utf-8可能会有点麻烦,一般utf-8文件开头会有BOM,如果使用session就会出问题,可用editplus来保存,在editplus中,工具->参数选择->文件->UTF-8签名,选择总是删除,再保存就可以去掉BOM信息了。
2. php本身不是Unicode的,所有substr之类的函数得改成mb_substr(需要装mbstring扩展);或者用iconv转码。
二.PHP与Mysql的数据交互
PHP与数据库的编码应一致
1. 修改mysql配置文件my.ini或my.cnf,mysql最好用utf8编码
[mysql]
default-character-set=utf8
[mysqld]
default-character-set=utf8
default-storage-engine=MyISAM
在[mysqld]下加入:
default-collation=utf8_bin
init_connect='SET NAMES utf8′
2. 在需要做数据库操作的php程序前加mysql_query(”set names ‘编码'”);,编码和php编码一致,如果php编码是gb2312那mysql编码就是gb2312,如果是utf-8那mysql编码就是utf8,这样插入或检索数据时就不会出现乱码了
三.PHP与操作系统相关
Windows和Linux的编码是不一样的,在Windows环境下,调用PHP的函数时参数如果是utf-8编码会出现错误,比如move_uploaded_file()、filesize()、readfile()等,这些函数在处理上传、下载时经常会用到,调用时可能会出现下面的错误:
Warning: move_uploaded_file()[function.move-uploaded-file]:failed to open stream: Invalid argument in …
Warning: move_uploaded_file()[function.move-uploaded-file]:Unable to move ” to ” in …
Warning: filesize() [function.filesize]: stat failed for … in …
Warning: readfile() [function.readfile]: failed to open stream: Invalid argument in ..
在Linux环境下用gb2312编码虽然不会出现这些错误,但保存后的文件名出现乱码导致无法读取文件,这时可先将参数转换成操作系统识别的编码,编码转换可用mb_convert_encoding(字符串,新编码,原编码)或iconv(原编码,新编码,字符串),这样处理后保存的文件名就不会出现乱码,也可以正常读取文件,实现中文名称文件的上传、下载。
其实还有更好的解决方法,彻底与系统脱离,也就不用考虑系统是何编码。可以生成一个只有字母和数字的序列作为文件名,而将原来带有中文的名字保存在数据库中,这样调用move_uploaded_file()就不会出现问题,下载的时候只需将文件名改为原来带有中文的名字。实现下载的代码如下
header(”Pragma: public”);
header(”Expires: 0″);
header(”Cache-Component: must-revalidate, post-check=0, pre-check=0″);
header(”Content-type: $file_type”);
header(”Content-Length: $file_size”);
header(”Content-Disposition: attachment; filename=\”$file_name\”");
header(”Content-Transfer-Encoding: binary”);
readfile($file_path);
$file_type是文件的类型,$file_name是原来的名字,$file_path是保存在服务上文件的地址。
四.再来总结一下为什么会乱码
一般来说,乱码的出现有2种原因,首先是由于编码(charset)设置错误,导致浏览器以错误的编码来解析,从而出现了满屏乱七八糟的“天书”,其次是文件被以错误的编码打开,然后保存,比如一个文本文件原先是GB2312编码的,却以UTF-8编码打开再保存。要解决上述乱码问题,首先需要知道开发中哪些环节涉及到了编码:
1、文件编码:指的是页面文件(.html,.php等)本身是以何种编码来保存的。记事本和Dreamweaver 在打开页面时候会自动识别文件编码因而不太会出问题。而ZendStudio却不会自动识别编码,它只会根据首选项的配置固定以某种编码打开文件,如果工作时候一不注意,用错误编码打开文件,做了修改之后一保存,乱码就出现了(我深有体会)。
2、页面申明编码:在HTML代码HEAD里面,可以用<meta http-equiv=”Content-Type” content=”text/html; charset=”XXX” />来告诉浏览器网页采用了什么编码,目前中文网站开发中XXX主要用的是GB2312和UTF-8两种编码。
3、数据库连接编码:指的是进行数据库操作时候以哪种编码与数据库传输数据,这里需要注意的是不要与数据库本身的编码混淆,比如MySQL内部默认是latin1编码,也就是说Mysql是以latin1编码来存储数据,以其他编码传输给Mysql的数据会被转换成latin1编码。
知道了WEB开发中哪些地方涉及到了编码,也就知道了乱码产生的原因:上述3项编码设置不一致,由于各种编码绝大部分是兼容ASCII的,所以英文符号不会出现,中文就倒霉了。
五.决战一些常见的错误情况与解决:
1、数据库采用UTF8编码,而页面申明编码是GB2312,这是最常见的产生乱码的原因。这时候在PHP脚本里面直接SELECT数据出来的就是乱码,需要在查询前先使用: mysql_query(”SET NAMES GBK”); 来设定MYSQL连接编码,保证页面申明编码与这里设定的连接编码一致(GBK是GB2312的扩展)。如果页面是UTF-8编码的话,可以用: mysql_query(”SET NAMES UTF8″);
注意是UTF8而不是一般用的UTF-8。假如页面申明的编码与数据库内部编码一致可以不设定连接编码。
注:事实上MYSQL的数据输入输出比上面讲的更复杂一些,MYSQL配置文件my.ini中定义了2个默认编码,分别是[client]里的default -character-set和[mysqld]里的default-character-set来分别设定默认时候客户端连接和数据库内部所采用的编码。我们上面指定的编码其实是MYSQL客户端连接服务器时候的命令行参数character_set_client,来告诉MYSQL服务器接受到的客户端数据是什么编码的,而不是采用默认编码。
2、页面申明编码与文件本身编码不一致,这种情况很少发生,因为如果编码不一致美工做页面时候在浏览器看到的就是乱码了。更多时候是发布以后修改一些小BUG,以错误编码打开页面然后保存导致的。或者是用某些FTP软件直接在线修改文件,比如CuteFTP,由于软件编码配置错误而导致转换错了编码。
3、一些租用虚拟主机的朋友,明明上述3项编码都设置正确了还是有乱码。比方说网页是GB2312编码的,IE等浏览器打开却总是识别成UTF-8,网页HEAD里面已经申明是GB2312了,手动修改浏览器编码为GB2312 后页面显示正常。产生原因是服务器Apache设定了服务器全局的默认编码,在httpd.conf里面加了AddDefaultCharset UTF-8。这时候服务器会首先发送HTTP头给浏览器,其优先级比页面里申明编码高,自然浏览器就识别错了。解决办法有2个,请管理员在配置文件自己的虚机里加上一条AddDefaultCharset GB2312来覆盖全局配置,或者在自己目录的.htaccess里配置。

总结:总之一句话,要解决PHP中文乱码最好最快的解决办法就是,页面申明的编码与数据库内部编码一致,如果页面申请的页码与数据库内部编码不一致时,就设定连接编码,mysql_query(”SET NAMES XXX”); XXX为连接编码.一定可以解决乱码的问题.

PHP 相关文章推荐
ThinkPHP采用模块和操作分析
Apr 18 PHP
php实现删除空目录的方法
Mar 16 PHP
php实现的通用图片处理类
Mar 24 PHP
Apache服务器下防止图片盗链的办法
Jul 06 PHP
PHP简单的MVC框架实现方法
Dec 01 PHP
thinkphp项目部署到Linux服务器上报错“模板不存在”如何解决
Apr 27 PHP
CI框架整合smarty步骤详解
May 19 PHP
PHP针对中英文混合字符串长度判断及截取方法示例
Mar 31 PHP
针对thinkPHP5框架存储过程bug重写的存储过程扩展类完整实例
Jun 16 PHP
PHP实现redis限制单ip、单用户的访问次数功能示例
Jun 16 PHP
PHP的mysqli_sqlstate()函数讲解
Jan 23 PHP
php获取小程序码的实现代码(B类接口)
Jun 13 PHP
PHP 变量定义和变量替换的方法
Jul 30 #PHP
PHP file_get_contents 函数超时的几种解决方法
Jul 30 #PHP
一个PHP数组应该有多大的分析
Jul 30 #PHP
PHP UTF8编码内的繁简转换类
Jul 20 #PHP
php 验证码制作(网树注释思想)
Jul 20 #PHP
php PDO中文乱码解决办法
Jul 20 #PHP
PHP 配置文件中open_basedir选项作用
Jul 19 #PHP
You might like
mysql limit查询优化分析
2008/11/12 PHP
php自定义函数之递归删除文件及目录
2010/08/08 PHP
PHP中加密解密函数与DES加密解密实例
2014/10/17 PHP
php实现复制移动文件的方法
2015/07/29 PHP
jQuery的一些注意
2006/12/06 Javascript
JavaScript 学习笔记(六)
2009/12/31 Javascript
从面试题学习Javascript 面向对象(创建对象)
2012/03/30 Javascript
js判断为空Null与字符串为空简写方法
2014/02/24 Javascript
深入理解JavaScript系列(35):设计模式之迭代器模式详解
2015/03/03 Javascript
javascript算法题:求任意一个1-9位不重复的N位数在该组合中的大小排列序号
2015/04/01 Javascript
如何解决ligerUI布局时Center中的Tab高度大小
2015/11/24 Javascript
JavaScript学习笔记整理_关于表达式和语句
2016/09/19 Javascript
浅谈javascript alert和confirm的美化
2016/12/15 Javascript
微信小程序动态显示项目倒计时效果
2017/06/13 Javascript
原生JS使用Canvas实现拖拽式绘图功能
2019/06/05 Javascript
vue路由插件之vue-route
2019/06/13 Javascript
浅谈Vue.use到底是什么鬼
2020/01/21 Javascript
Node.js API详解之 assert模块用法实例分析
2020/05/26 Javascript
JS中的变量作用域(console版)
2020/07/18 Javascript
vue element el-transfer增加拖拽功能
2021/01/15 Vue.js
使用Python判断IP地址合法性的方法实例
2014/03/13 Python
python日期相关操作实例小结
2019/06/24 Python
关于Python内存分配时的小秘密分享
2019/09/05 Python
使用python代码进行身份证号校验的实现示例
2019/11/21 Python
Python3 字典dictionary入门基础附实例
2020/02/10 Python
浅谈PyTorch的可重复性问题(如何使实验结果可复现)
2020/02/20 Python
Spark处理数据排序问题如何避免OOM
2020/05/21 Python
python中tkinter窗口位置\坐标\大小等实现示例
2020/07/09 Python
HTML5 新事件 小结
2009/07/16 HTML / CSS
巴西宠物商店:Cobasi
2019/04/19 全球购物
计算机专业优秀大学生自我总结
2014/01/21 职场文书
幼儿园教师考核制度
2014/02/01 职场文书
群教班子对照检查材料
2014/08/26 职场文书
房屋登记授权委托书范本
2014/10/09 职场文书
画展观后感
2015/06/17 职场文书
2016计算机专业毕业生自荐信
2016/01/28 职场文书