作者:360weboy
新浪微博:http://weibo.com/360weboy
博文链接: http://www.360weboy.com/php/fundament/charset.html上个星期在为一个电子商务网站进行数据转移到新系统中的时候,发现一些产品描述字符老是输出乱码,确定是字符集的问题以后,对字符集再次进行了一次调研,确定了影响页面字符集的方式主要下面几种方式:
1. 文件的编码方式
2. Apache2的默认字符集设置
3. PHP.ini中的默认字符集的设置
4. PHP脚本中手动输出header(‘Content-type:text/html;charset=xxx’);
5. html页面中加入
我对以上五种方式都进行了一一测试,并且确定了5种方式对于浏览器字符集选择的优先级。首先我创建了一个以utf8编码的test.php文件,内容如下:我使用chrome访问test.php, 因为我的chrome浏览器的默认字符集不是utf8,应该是gb2312或者gbk,所以我在浏览器中看到了如下乱码:header与meta的优先级比较接下来,先来测试以上的4,5两种方式。我向html页面中分别加入了,内容显示正常。去掉header中的meta标签,加入header(‘Content-type:text/html;charset=utf8′);内容显示正常。那么,meta标签和header的方式,那个优先级高呢,我在页面里同时设置了这两项,header设置为gb2312, meta设置为utf8:结果内容显示不正常,说明header的优先级高。浏览器先采用http头部中的字符集设置,然后是html页面中meta标签设置的字符集。php.ini中设置默认字符集以后的影响接下来,我们来看下在php.ini中设置默认字符集以后的情形。为了测试下优先级,我们先将页面中的header以及meta设置的字符集都改为gb2312,那么这样内容肯定显示为乱码。然后,我们打开php.ini文件,找到如下设置,去掉前面的引号,设置字符集为utf8:设置好以后,记得要重启下apache2服务器,结果显示如下:我们看到,在php.ini设置默认字符集为utf8以后,它被加入到了响应头Content-type末尾,从而覆盖了在php脚本中通过header函数输出的gb2312的字符集,浏览器根据该头部中的信息,认为内容是utf8的字符集,最后内容现实正常。由此可见,php.ini中字符集设置的优先级高于header函数以及meta标签。apache2中设置默认字符集最后,我们来设置下apache2中的默认字符集来测试下。这次将header,meta,php.ini中的字符集都设置为gb2312,然后在apache2设置默认字符集为utf8:重启apache2服务器,内容显示如下:由此可见,apache2中的字符集的设置没有影响到http响应中的Content-Type头部,所以浏览器认为应该用gb2312来解码,导致出现乱码。那么,如果去掉php.ini中的字符集的设置以后内,页面是否会显示正常。经过测试,显示如下:看来,apache2中的字符集的优先级同样小于header函数的字符集设置。我们继续去掉header的设置看下:以上证明,apache2中的字符集设置的优先级高于meta标签的字符集设置。charset=utf8加入到了http头部中。
综合上述实验,得出字符集设置优先级顺序: php.ini默认字符集设置 > header函数字符集设置 > apache2默认字符集设置 > meta标签字符集设置字符集

解决方案 »

  1.   

    为什么实验过程没有问题,但得出的结论是错误的呢?
    经测试:
    default_charset 的优先级小于 header 函数字符集设置
      

  2.   

    snmr_com请指教,你知道测试问题所在,那么能不能说下,这个过程应该怎么测试才算标准。。多谢!
      

  3.   

    http://www.w3help.org/zh-cn/causes/HR9001
    可以参考这边文章,但这文章也比较旧了你用的是归纳法推导,完全归纳法的基础就是满足所有的可能性得出一致(唯一)结论
    并且,因为你的这个命题各种可能性并非符合“良序”特性,不能用数学归纳法那样的两步求证
    所以,你要做测试就要遍历所有的可能性,如果没有遍历所有可能性,那么结论就只能增加限定条件
    例如
    只涉及一种浏览器,结论就只能缩小到该浏览器
    原文档只使用了一种编码,那结论也只能适用于这种编码基本上增加了两三个限定条件,结论就没有太大的实用意义,因为适用范围变得很小了
    所以还是要做更多的测试以支持你的结论才行
    你命题涉及的条件有:浏览器、各优先级的编码指定、语系(特别是较难自动识别的不同语系,如同是双字节中日韩编码)、文档编码,做一个排列组合,可能性就相当多了……如果能全部测试一遍,还是相当佩服你的,呵呵
      

  4.   

    php.ini运行界面
    你测试的结果并不代表我测试的结果
    何况 header 就该能改变相关预设值,否则还要他干什么?
      

  5.   

    没错header可以改变,那为啥还要其它方法,有其它方法的存在,就说明有它存在的必要对于技术,只是希望搞的清晰而已,再牛逼的技术,在我看来就是一种实现的方法。。我发贴不是要跟那个搞技术的论高下