ajax+php应用的乱码问题分析与解决
来源:互联网 发布:如何安装proteus软件 编辑:程序博客网 时间:2024/06/15 05:08
出处:www.phpchina.com 作者:jidixuelang 时间:2007年3月2日 本站原创,转帖请注明出处
下期预告:ajax+php实现title效果全面解析
相信做ajax+php应用的朋友都遇到过乱码的问题
现在,你们是不是都有了自己的一套解决方案呢?
我原来推荐朋友做AJAX应用时,使用全UTF-8编码.其实是在逃避问题
而且大家应该会注意到,很多ajax应用前台HTML并不是UTF-8的
鉴于很多初学者,仍然为此困惑.我这里抛砖引玉
洋洋洒洒写了一大堆,别嫌我罗嗦
我在网上写东西一般是想到什么写什么,不咋检查滴.出现什么逻辑错误,或者影响理解的错别字,请指出!谢谢
注意红色的和加粗的部分
明确问题:
很多朋友出现乱码后,就在论坛发帖,或网上搜寻相关文章 .
然后,很快就认识了 header("content-type:text/html; charset=utf-8"),iconv('gbk', 'utf-8', " ...."),mysql_query(set names xxx)
以及一个什么php实现的unescape函数等等
甚至连为什么产生乱码都没去想,问题有时候还真被解决了 [这就是互联网的神奇之处]
其实,根本问题很容易理解,就是存储方式和读取方式不一致
你存储的是一段utf-8编码的文字,却告诉浏览器用gb2312的方式去解析.问题自然就来了!
如下面这段代码,用记事本保存为html文件,IE打开是没有任何问题的!如果你把第四行的gb2312改为utf-8那问题自然就来了
因为记事本默认的是用ANSI标准保存,而gb2312是其中的一种!对于简体中文的操作系统,我们存储的是一段gb2312数据!如果你骗浏览器这
是一段utf-8的数据,那这个忠实的仆人自然就会犯错误了![gb2312改成utf-8(请在记事本中修改)后,标题和内容成乱码了]
整个ajax+php应用中,数据要转手两次 存在于三个层次中 分别是前台html 后台php 以及数据库
下面将按一个读取的过程,依次分析两次转手的过程
数据库<->php过程分析
mysql编码问题,应该是我们论坛的朋友最熟悉的,就不多说了!
而且没有什么可说的,你只要能确定你当前数据库中的数据不是乱码就行了
这里,提一下 mysql_query("SET NAMES '编码格式如(utf8)'")
我找了一段网上关于set names 的说明:
感觉它说得不够俗,咱来通俗点:
其实,他的作用就是告诉数据库,"我传给你的将是一段X编码的数据,请按X编码理解","你传给我的数据也必须翻译成X编码的,我只懂X编码"
注意上面的两个引号部分,这说明他分别设定了读取和写入两个层次
所以在PHP读取MYSQL中的数据的时候,只要你的数据库中的数据本身不是乱码!你执行mysql_query("SET NAMES '编码格式如(utf8)'")后,
读取出来的数据,都将是UTF-8格式的正常数据!同理,只要你执行sql 语句里的数据都是utf-8格式的,存如数据库后都不会是乱码.
下面来做个实验:
请将header("content-type:text/html; charset=utf-8"); 改为header("content-type:text/html; charset=gb2312"); 再测试一下
这从侧面说明了header的作用 他并未转换任何数据 而仅仅通知一下浏览器应该用什么方式理解数据 这是浏览器对http协议的实现,我们不用管它
ps:
对PHP应用来说,乱码问题到此已经结束.但对ajax+php应用来说,还没有,还有一个php经ajax处理-到HTML页面的过程
后面将分别对IE浏览器和非IE浏览器 做进一步讲解
这部分写完了,还没跟大家说在PHP部分究竟应该怎么做! 为什么?晚上写完了你就知道了!
这里理解一下,set names iconv 和header先
HTML<->PHP过程分析
接着中午的讲.
本来说,按IE和非IE浏览器分别讲一下,php与前台通过ajax交互这一过程的.细想了下,发现没这必要! [文中的非IE浏览器指FF和OPERA]
这两类浏览器对ajax的实现区别很大,但这个具体的实现对我门程序员来说是透明的 我们没有必要去深究
我们只要知道具体应用的时候,有哪些需要注意的地方就行了
IE是通过内置的ActiveXObject来实现ajax的,而非IE浏览器是用XMLHttpRequest类来实现的.一些细微的差别因此而来!
以下是我自己总结的几条规律:[初看的时候,你可能不理解,下面会一一解释]
1.AJAX读取的时候,对IE浏览器来说,只要php端传给他的是UTF-8的数据,他就能正常显示.
2.AJAX读取的时候,对非IE浏览器来说.只要数据在php本身能正常显示,他被传到浏览器中也能正常显示.
3.AJAX写入的时候,IE与非IE浏览器是一样的.不管你在浏览器端是什么编码格式的数据,被传到PHP中后,都将变成正常的UTF-8格式数据!
四楼有张图,可以参照一下
针对IE:
这里先说一下,传给他是UTF-8数据是什么意思.请看下面这两段代码!
[这里默认为你的编辑器用gb2312格式保存文件!这点很重要!若不是,结果将不同!但不代表原理有误!]
虽然以上两段代码执行后,一段乱码,一段正常!
但不可否认,经过iconv处理后,他门输出的都是UTF-8编码的数据!
如前面所说:"AJAX读取的时候,对IE浏览器来说,只要php端传给他的是UTF-8的数据,他就能正常显示."
因此,这两段代码在IE下,用AJAX读取过去,都将是正常显示的!
测试HTML页面 [请将上面的两段PHP依次保存为test.php.与该HTML文件放同一目录下做测试]
IE下测试均正常的.而FF和OPERA下,用第一段PHP测试的话将是乱码!
针对非IE浏览器[FF,OPERA]:
下面再引入第三段PHP
这段php直接执行是能正常显示的,不会出现乱码!
它和第二段php一起佐证我的第二个结论:
"AJAX读取的时候,对非IE浏览器来说.只要数据在php本身能正常显示,他被传到浏览器中也能正常显示."
所以,你用第二和第三段PHP做为test.php的话 ,会发现test.html页面在ff与opera下均是正常的!而用第三段的话ie下是乱码!
你真的理解了,我总结的这两条了吗? 请思考,5楼留下的那个题目!
至于,第三个结论,请自行证明!因为要证明的话,最好联系数据库做测试最好!我这里就不做了!
最终结论:
我们只要保证三点,就可以使你的AJAX+PHP应用中不出现乱码了!而且是兼容各种浏览器的!
1.在php页面中,使用mysql_query("SET NAMES 'UTF8'");读取数据库中的文件!
2.在文件前面设置header("content-type:text/html; charset=utf-8")
3.php文件中不能出现一个汉字!这些汉字多办是不必要的,或是应该直接保存在js文件中的![初学者喜欢用中文表名的毛病也要注意了.]
至于9楼所说的那种采集程序,没用到数据库.正好可以归为另一类.就要用到iconv了之类的转换函数了
对于这类ajax应用,我们前面得到的最终结论,你只要改动第一条就行了
1.在php页面中,使用iconv('gbk', 'utf-8', $test); iconv('gb2312', 'utf-8', $test)将获取的数据转换成utf-8编码就行了!
[当然,被采集的页面本身是utf-8编码就不需要转换了,但其他两条仍需遵守!]
综上,你的php页面能正常的取到utf-8数据,输出的文件头(header())为utf-8就不会出现乱码!
关键还是理解在各个过程中,编码的变化过程! 以及IE与非IE浏览器的区别!
[请点击查看大图]
[attach]8651[/attach]
[常见问题列表:]
1.Cannot add header information - headers already sent by ...错误!
这是UTF-8头问题!你找一个能显示UTF-8头的编辑器,会看到你的PHP页面开头是"锘?<?php".这是你的编辑器转换页面格式的时候自动添加上去的,少数编辑器可以通过设置禁止.
2.data too long for column 错误
请不要从字面上理解这个错误! 在AJAX应用中,这个错误通常是由于你的SQL语句和数据的编码中有中文且和set names 的格式不一样(如果你没设置set names 那就是和数据库的默认设置不一样),从而出现乱码造成的!
还有一种情况看这个帖子:http://www.phpchina.com/bbs/thread-19695-1-1.html
下期预告:ajax+php实现title效果全面解析
相信做ajax+php应用的朋友都遇到过乱码的问题
现在,你们是不是都有了自己的一套解决方案呢?
我原来推荐朋友做AJAX应用时,使用全UTF-8编码.其实是在逃避问题
而且大家应该会注意到,很多ajax应用前台HTML并不是UTF-8的
鉴于很多初学者,仍然为此困惑.我这里抛砖引玉
洋洋洒洒写了一大堆,别嫌我罗嗦
我在网上写东西一般是想到什么写什么,不咋检查滴.出现什么逻辑错误,或者影响理解的错别字,请指出!谢谢
注意红色的和加粗的部分
明确问题:
很多朋友出现乱码后,就在论坛发帖,或网上搜寻相关文章 .
然后,很快就认识了 header("content-type:text/html; charset=utf-8"),iconv('gbk', 'utf-8', " ...."),mysql_query(set names xxx)
以及一个什么php实现的unescape函数等等
甚至连为什么产生乱码都没去想,问题有时候还真被解决了 [这就是互联网的神奇之处]
其实,根本问题很容易理解,就是存储方式和读取方式不一致
你存储的是一段utf-8编码的文字,却告诉浏览器用gb2312的方式去解析.问题自然就来了!
如下面这段代码,用记事本保存为html文件,IE打开是没有任何问题的!如果你把第四行的gb2312改为utf-8那问题自然就来了
因为记事本默认的是用ANSI标准保存,而gb2312是其中的一种!对于简体中文的操作系统,我们存储的是一段gb2312数据!如果你骗浏览器这
是一段utf-8的数据,那这个忠实的仆人自然就会犯错误了![gb2312改成utf-8(请在记事本中修改)后,标题和内容成乱码了]
[Copy to clipboard] [ - ]
CODE:<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312" />
<title>无标题文档</title>
</head>
<body>
<p>无标题文档</p>
</body>
</html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312" />
<title>无标题文档</title>
</head>
<body>
<p>无标题文档</p>
</body>
</html>
整个ajax+php应用中,数据要转手两次 存在于三个层次中 分别是前台html 后台php 以及数据库
下面将按一个读取的过程,依次分析两次转手的过程
数据库<->php过程分析
mysql编码问题,应该是我们论坛的朋友最熟悉的,就不多说了!
而且没有什么可说的,你只要能确定你当前数据库中的数据不是乱码就行了
这里,提一下 mysql_query("SET NAMES '编码格式如(utf8)'")
我找了一段网上关于set names 的说明:
[复制PHP代码] [ - ]
PHP代码如下:SET NAMES显示客户端发送的SQL语句中使用什么字符集。因此,SET NAMES 'cp1251'语句告诉服务器“将来从这个客户端传来的信息采用字符集cp1251”。它还为服务器发送回客户端的结果指定了字符集。(例如,如果你使用一个SELECT语句,它表示列值使用了什么字符集。)
SET NAMES 'x'语句与这三个语句等价:
mysql> SET character_set_client = x;
mysql> SET character_set_results = x;
mysql> SET character_set_connection = x;
将x设置为character_set_connection也就设置了collation_connection是x的默认校对规则。
SET NAMES 'x'语句与这三个语句等价:
mysql> SET character_set_client = x;
mysql> SET character_set_results = x;
mysql> SET character_set_connection = x;
将x设置为character_set_connection也就设置了collation_connection是x的默认校对规则。
感觉它说得不够俗,咱来通俗点:
其实,他的作用就是告诉数据库,"我传给你的将是一段X编码的数据,请按X编码理解","你传给我的数据也必须翻译成X编码的,我只懂X编码"
注意上面的两个引号部分,这说明他分别设定了读取和写入两个层次
所以在PHP读取MYSQL中的数据的时候,只要你的数据库中的数据本身不是乱码!你执行mysql_query("SET NAMES '编码格式如(utf8)'")后,
读取出来的数据,都将是UTF-8格式的正常数据!同理,只要你执行sql 语句里的数据都是utf-8格式的,存如数据库后都不会是乱码.
下面来做个实验:
[复制PHP代码] [ - ]
PHP代码如下:
<?php
/*
......省略......
$conn = mysql_connect($hostname,$username,$password);
mysql_query("SET NAMES 'UTF8'");
......省略......
类似以上方式随便在数据库中读取一段数据,他都将保存成一段utf-8格式编码的数据
这里为了你测试方便,我用iconv函数模拟了一下 [本页左上方,可以查看iconv的详细内容]
如楼上所说,用记事本保存这段代码,所有数据格式将是gb2312的 因此下面的变量$test未经过iconv之前,将是gb2312格式的数据!
经过iconv后 变成一段utf-8格式的数据
而输出的HTML 如果你不手动设置一下header 各个浏览器的处理方式是不一样 有兴趣的可以自行测试一下
所以为了统一一下,这里设置一下header
执行结果第一行将是乱玛,第二行是正常的! 为什么 应该还是很容易理解的吧!
*/
header("content-type:text/html; charset=utf-8");
$test = "大家好!";
echo $test."<br />";
$test = iconv('gbk', 'utf-8', $test); //我假设这个将是你从数据库中读出来的正常的UTF-8数据
echo $test;
?>
请将header("content-type:text/html; charset=utf-8"); 改为header("content-type:text/html; charset=gb2312"); 再测试一下
这从侧面说明了header的作用 他并未转换任何数据 而仅仅通知一下浏览器应该用什么方式理解数据 这是浏览器对http协议的实现,我们不用管它
ps:
对PHP应用来说,乱码问题到此已经结束.但对ajax+php应用来说,还没有,还有一个php经ajax处理-到HTML页面的过程
后面将分别对IE浏览器和非IE浏览器 做进一步讲解
这部分写完了,还没跟大家说在PHP部分究竟应该怎么做! 为什么?晚上写完了你就知道了!
这里理解一下,set names iconv 和header先
HTML<->PHP过程分析
接着中午的讲.
本来说,按IE和非IE浏览器分别讲一下,php与前台通过ajax交互这一过程的.细想了下,发现没这必要! [文中的非IE浏览器指FF和OPERA]
这两类浏览器对ajax的实现区别很大,但这个具体的实现对我门程序员来说是透明的 我们没有必要去深究
我们只要知道具体应用的时候,有哪些需要注意的地方就行了
IE是通过内置的ActiveXObject来实现ajax的,而非IE浏览器是用XMLHttpRequest类来实现的.一些细微的差别因此而来!
以下是我自己总结的几条规律:[初看的时候,你可能不理解,下面会一一解释]
1.AJAX读取的时候,对IE浏览器来说,只要php端传给他的是UTF-8的数据,他就能正常显示.
2.AJAX读取的时候,对非IE浏览器来说.只要数据在php本身能正常显示,他被传到浏览器中也能正常显示.
3.AJAX写入的时候,IE与非IE浏览器是一样的.不管你在浏览器端是什么编码格式的数据,被传到PHP中后,都将变成正常的UTF-8格式数据!
四楼有张图,可以参照一下
针对IE:
这里先说一下,传给他是UTF-8数据是什么意思.请看下面这两段代码!
[这里默认为你的编辑器用gb2312格式保存文件!这点很重要!若不是,结果将不同!但不代表原理有误!]
[复制PHP代码] [ - ]
PHP代码如下:
<?php
header("content-type:text/html; charset=gb2312");
$test = "大家好!";
$test = iconv('gbk', 'utf-8', $test);
echo $test;
?>
[复制PHP代码] [ - ]
PHP代码如下:
<?php
header("content-type:text/html; charset=utf-8");
$test = "大家好!";
$test = iconv('gbk', 'utf-8', $test);
echo $test;
?>
虽然以上两段代码执行后,一段乱码,一段正常!
但不可否认,经过iconv处理后,他门输出的都是UTF-8编码的数据!
如前面所说:"AJAX读取的时候,对IE浏览器来说,只要php端传给他的是UTF-8的数据,他就能正常显示."
因此,这两段代码在IE下,用AJAX读取过去,都将是正常显示的!
测试HTML页面 [请将上面的两段PHP依次保存为test.php.与该HTML文件放同一目录下做测试]
[Copy to clipboard] [ - ]
CODE:<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312" />
<title>无标题文档</title>
<script type="text/javascript">
function manageres()
{
var objText = this.req.responseText;
var objChange = document.getElementById("result");
objChange.innerHTML = objText;
}
function createrep() {
if (typeof XMLHttpRequest != "undefined") {
return new XMLHttpRequest();
}
else if (window.ActiveXObject) {
var Versions = [ "MSXML2.XMLHttp.5.0","MSXML2.XMLHttp.4.0","MSXML2.XMLHttp.3.0","MSXML2.XMLHttp","Microsoft.XMLHttp"];
for (var i = 0; i < Versions.length; i++) {
try {
var XMLHttp = new ActiveXObject(Versions);
return XMLHttp;
}
catch (e) {}
}
}
}
var net=new Object();
net.ContentLoader=function(){
this.req=null;
this.onload=manageres;
}
net.ContentLoader.prototype={
loadXMLDoc:function(query){
this.req=createrep();
if (this.req){
var loader=this;
this.req.open('GET',"test.php?date="+new Date().getTime(),true);
this.req.onreadystatechange=function(){
loader.onReadyState.call(loader);
}
this.req.send(null);
}
},
onReadyState:function(){
var req=this.req;
var ready=req.readyState;
if (ready==4){
var httpStatus=req.status;
if (httpStatus==200 || httpStatus==0){
this.onload.call(this);
}
}
}
}
var selector = new net.ContentLoader();
</script>
</head>
<body onload="selector.loadXMLDoc();">
<div id="result"></div>
</body>
</html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312" />
<title>无标题文档</title>
<script type="text/javascript">
function manageres()
{
var objText = this.req.responseText;
var objChange = document.getElementById("result");
objChange.innerHTML = objText;
}
function createrep() {
if (typeof XMLHttpRequest != "undefined") {
return new XMLHttpRequest();
}
else if (window.ActiveXObject) {
var Versions = [ "MSXML2.XMLHttp.5.0","MSXML2.XMLHttp.4.0","MSXML2.XMLHttp.3.0","MSXML2.XMLHttp","Microsoft.XMLHttp"];
for (var i = 0; i < Versions.length; i++) {
try {
var XMLHttp = new ActiveXObject(Versions);
return XMLHttp;
}
catch (e) {}
}
}
}
var net=new Object();
net.ContentLoader=function(){
this.req=null;
this.onload=manageres;
}
net.ContentLoader.prototype={
loadXMLDoc:function(query){
this.req=createrep();
if (this.req){
var loader=this;
this.req.open('GET',"test.php?date="+new Date().getTime(),true);
this.req.onreadystatechange=function(){
loader.onReadyState.call(loader);
}
this.req.send(null);
}
},
onReadyState:function(){
var req=this.req;
var ready=req.readyState;
if (ready==4){
var httpStatus=req.status;
if (httpStatus==200 || httpStatus==0){
this.onload.call(this);
}
}
}
}
var selector = new net.ContentLoader();
</script>
</head>
<body onload="selector.loadXMLDoc();">
<div id="result"></div>
</body>
</html>
IE下测试均正常的.而FF和OPERA下,用第一段PHP测试的话将是乱码!
针对非IE浏览器[FF,OPERA]:
下面再引入第三段PHP
[复制PHP代码] [ - ]
PHP代码如下:
<?php
header("content-type:text/html; charset=gb2312");
$test = "大家好!";
echo $test;
?>
这段php直接执行是能正常显示的,不会出现乱码!
它和第二段php一起佐证我的第二个结论:
"AJAX读取的时候,对非IE浏览器来说.只要数据在php本身能正常显示,他被传到浏览器中也能正常显示."
所以,你用第二和第三段PHP做为test.php的话 ,会发现test.html页面在ff与opera下均是正常的!而用第三段的话ie下是乱码!
你真的理解了,我总结的这两条了吗? 请思考,5楼留下的那个题目!
至于,第三个结论,请自行证明!因为要证明的话,最好联系数据库做测试最好!我这里就不做了!
最终结论:
我们只要保证三点,就可以使你的AJAX+PHP应用中不出现乱码了!而且是兼容各种浏览器的!
1.在php页面中,使用mysql_query("SET NAMES 'UTF8'");读取数据库中的文件!
2.在文件前面设置header("content-type:text/html; charset=utf-8")
3.php文件中不能出现一个汉字!这些汉字多办是不必要的,或是应该直接保存在js文件中的![初学者喜欢用中文表名的毛病也要注意了.]
至于9楼所说的那种采集程序,没用到数据库.正好可以归为另一类.就要用到iconv了之类的转换函数了
对于这类ajax应用,我们前面得到的最终结论,你只要改动第一条就行了
1.在php页面中,使用iconv('gbk', 'utf-8', $test); iconv('gb2312', 'utf-8', $test)将获取的数据转换成utf-8编码就行了!
[当然,被采集的页面本身是utf-8编码就不需要转换了,但其他两条仍需遵守!]
综上,你的php页面能正常的取到utf-8数据,输出的文件头(header())为utf-8就不会出现乱码!
关键还是理解在各个过程中,编码的变化过程! 以及IE与非IE浏览器的区别!
[请点击查看大图]
[attach]8651[/attach]
[常见问题列表:]
1.Cannot add header information - headers already sent by ...错误!
这是UTF-8头问题!你找一个能显示UTF-8头的编辑器,会看到你的PHP页面开头是"锘?<?php".这是你的编辑器转换页面格式的时候自动添加上去的,少数编辑器可以通过设置禁止.
2.data too long for column 错误
请不要从字面上理解这个错误! 在AJAX应用中,这个错误通常是由于你的SQL语句和数据的编码中有中文且和set names 的格式不一样(如果你没设置set names 那就是和数据库的默认设置不一样),从而出现乱码造成的!
还有一种情况看这个帖子:http://www.phpchina.com/bbs/thread-19695-1-1.html
- ajax+php应用的乱码问题分析与解决
- PHP解决AJAX乱码问题
- JAVA中应用AJAX的中文乱码问题的解决
- php解析XML和AJAX时乱码问题的解决
- C#与PHP制作WEBSERVICE接口时,部分中文是乱码问题的分析与解决
- php+ajax解决中文乱码问题
- 解决Ajax乱码问题
- 解决ajax乱码问题
- Java Web中常见乱码问题的分析与解决
- 解决java+ajax的乱码问题
- Ajax 中文乱码问题的解决
- 解决jQuery中Ajax的乱码问题
- 解决ajax返回乱码的问题
- jsp 解决ajax乱码的问题
- 关于php中ajax运用时的中文乱码问题的解决
- 【原】解决php ajax乱码
- 对于如何解决wicket Ajax 自动提示应用中出现的乱码问题!
- PHP解决乱码问题
- ANTHILL 自动化构建
- ORACLE 常用的SQL语法和数据对象
- 了解SQL Server锁争用:NOLOCK 和 ROWLOCK 的秘密
- mac os x下软件本地化及测试
- bat文件使用简介
- ajax+php应用的乱码问题分析与解决
- 07胡润IT富豪榜发布:李彦宏成IT首富
- 人体缺乏维生素B会怎样
- ubuntu-7.04-dvd-i386.iso硬盘安装方法
- CCIE试验备考之交换TRUNK(待看)
- 巧用 CCProxy 阻止非法下载
- 对静态变量和全局变量的认识
- 做投机别太多主观
- 对象的序列化和反序列化实践