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 相关文章推荐
高亮度显示php源代码
Oct 09 PHP
fleaphp rolesNameField bug解决方法
Apr 23 PHP
CodeIgniter采用config控制的多语言实现根据浏览器语言自动转换功能
Jul 18 PHP
PHP自带ZIP压缩、解压缩类ZipArchiv使用指南
Mar 03 PHP
WordPress中给文章添加自定义字段及后台编辑功能区域
Dec 19 PHP
ThinkPHP设置禁止百度等搜索引擎转码(简单实用)
Feb 15 PHP
php读取torrent种子文件内容的方法(测试可用)
May 03 PHP
PHP简单遍历对象示例
Sep 28 PHP
PHP新特性详解之命名空间、性状与生成器
Jul 18 PHP
Yii框架学习笔记之session与cookie简单操作示例
Apr 30 PHP
PHP 对象继承原理与简单用法示例
Apr 21 PHP
PHP isset empty函数相关面试题及解析
Dec 11 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
PHP仿博客园 个人博客(1) 数据库与界面设计
2013/07/05 PHP
PHP链接MySQL的常用扩展函数
2014/10/23 PHP
利用php + Laravel如何实现部署自动化详解
2017/10/11 PHP
Yii1.1框架实现PHP极光推送消息通知功能
2018/09/06 PHP
日期函数扩展类Ver0.1.1
2006/09/07 Javascript
JavaScript replace(rgExp,fn)正则替换的用法
2010/03/04 Javascript
AJAX使用了UpdatePanel后无法使用alert弹出脚本
2010/04/02 Javascript
扩展JS Date对象时间格式化功能的小例子
2013/12/02 Javascript
javascript中AJAX用法实例分析
2015/01/30 Javascript
jquery动态改变div宽度和高度
2015/02/09 Javascript
jQuery实现鼠标滑向当前图片高亮显示并且其它图片变灰的方法
2015/07/27 Javascript
js当前页面登录注册框,固定div,底层阴影的实例代码
2016/10/04 Javascript
js 两个日期比较相差多少天的实例
2017/10/19 Javascript
JS重学系列之聊聊new操作符
2019/03/04 Javascript
细说webpack6 Babel的使用详解
2019/09/26 Javascript
js+canvas实现两张图片合并成一张图片的方法
2019/11/01 Javascript
记一次用ts+vuecli4重构项目的实现
2020/05/21 Javascript
浅谈实现在线预览PDF的几种解决办法
2020/08/10 Javascript
[02:15]2014DOTA2国际邀请赛 赛后退役选手回顾
2014/08/01 DOTA
[00:36]DOTA2上海特级锦标赛 LGD战队宣传片
2016/03/04 DOTA
Python使用scrapy采集数据时为每个请求随机分配user-agent的方法
2015/04/08 Python
python3将视频流保存为本地视频文件
2018/06/20 Python
pandas 按照特定顺序输出的实现代码
2018/07/10 Python
python实现beta分布概率密度函数的方法
2019/07/08 Python
python opencv对图像进行旋转且不裁剪图片的实现方法
2019/07/09 Python
python增加图像对比度的方法
2019/07/12 Python
Python Django 命名空间模式的实现
2019/08/09 Python
numpy求平均值的维度设定的例子
2019/08/24 Python
Python tensorflow实现mnist手写数字识别示例【非卷积与卷积实现】
2019/12/19 Python
Django 自定义404 500等错误页面的实现
2020/03/08 Python
浅谈TensorFlow中读取图像数据的三种方式
2020/06/30 Python
结合CSS3的布局新特征谈谈常见布局方法
2016/01/22 HTML / CSS
麦德龙官方海外旗舰店:德国麦德龙超市
2017/12/23 全球购物
优秀员工个人的自我评价
2013/11/29 职场文书
大学生个人年度总结范文
2015/02/15 职场文书
廉政承诺书范文
2015/04/28 职场文书