2008年07月14日

Apache和PHP网页的编码问题分析

谈到Apache的编码我们就要涉及到3个东西

http标记语言中的<META http-equiv="content-type" content="text/html; charset=xxx">标签
PHP中的header("content-type:text/html; charset=xxx");函数
Apache配置文件httpd.conf中的AddDefaultCharset

一、<META http-equiv="content-type" content="text/html; charset=xxx">标签
按顺序来,先说这个<META>标签,这个标签有很多功能的,具体请点这里。


我今天想说只是上面提到的那种形式。解释一下<META http-equiv="content-type" content="text/html; charset=utf-8">,意思是对这个网页进行声明,让浏览器对整个页面的内容采用xxx编码,xxx可以为GB2312,GBK,UTF-8(和MySQL不同,MySQL是UTF8)等等。因此,大部分页面可以采用这种方式来告诉浏览器显示这个页面的时候采用什么编码,这样才不会造成编码错误而产生乱码。但是有的时候我们会发现有了这句还是不行,不管xxx是哪一种,浏览器采用的始终都是一种编码,这个情况我后面会谈到。

请注意,<meta>是属于html信息的,仅仅是一个声明,它起作用表明服务器已经把HTML信息传到了浏览器。

二、header("content-type:text/html; charset=xxx");
这个函数header()的作用是把括号里面的信息发到http标头。关于此函数具体用法请点击这里。
如果括号里面的内容为文中所说那样,那作用和<META>标签基本相同,大家对照第一个看发现字符都差不多的。但是不同的是如果有这段函数,浏览器就会永远采用你所要求的xxx编码,绝对不会不听话,因此这个函数是很有用的。为什么会这样呢?那就得说说HTTPS标头和HTML信息的差别了:
引用:
https标头是服务器以HTTP协议传送HTML信息到浏览器前所送出的字串。
因为meta标签是属于html信息的,所以header()发送的内容先到达浏览器,通俗点就是header()的优先级高于meta(不知道可不可以这样讲)。加入一个php页面既有header("content-type:text/html; charset=xxx"),又有<META http-equiv="content-type" content="text/html; charset=xxx">,浏览器就只认前者http标头而不认meta了。当然这个函数只能在php页面内使用。
同样也留有一个问题,为什么前者就绝对起作用,而后者有时候就不行呢?这就是接下来要谈的Apache的原因了。

三、AddDefaultCharset
Apache根目录的conf文件夹里,有整个Apache的配置文档httpd.conf。具体如何配置apache请点击这里([url=thread-2674-1-1.html]windows[/url],[url=thread-1381-1-1.html]linux[/url])。
用文本编辑器打开httpd.conf,第708行(不同版本可能不同)有AddDefaultCharset xxx,xxx为编码名称。这行代码的意思:设置整个服务器内的网页文件https标头里的字符集为你默认的xxx字符集。有这行,就相当于给每个文件都加了一行header("content-type:text/html; charset=xxx")。这下就明白为什么明明meta设置了是utf-8,可浏览器始终采用gb2312的原因。
如果网页里有header("content-type:text/html; charset=xxx"),就把默认的字符集改为你设置的字符集,所以这个函数永远有用。如果把AddDefaultCharset xxx前面加个“#”,注释掉这句,而且页面里不含header("content-type…"),那这个时候就轮到meta标签起作用了。

总结:
来个排序

header("content-type:text/html; charset=xxx")
AddDefaultCharset xxx
<META http-equiv="content-type" content="text/html; charset=xxx">
如果你是web程序员,给你的每个页面都加个header("content-type:text/html; charset=xxx"),保证它在任何服务器都能正确显示,可移植性强。

至于那句AddDefaultCharset xxx,要不要注释就仁者见仁了。反正我是注释掉了,不过我写页子也要写header(),便于放到不同的服务器上能正常显示。

  • » 阅读全文...
  • 2007年10月30日

    把o-blog的编码转换为utf8的过程

            前几天我把我使用的o-blog转换为utf8了。现在我整理了一下资料,把转换的过程记录下来,与大家分享一下经验,希望o-blog的新版本中可以出现utf8版本。我现在使用 o-blog 的版本为2.6如果版本不对,请你下载2.6版本.
           在转换之前,我有必要提醒你一下,你必须要把所有的网页和数据库的内容备份一下,万一转换的过程失败,你也可以迅速恢复数据或者可以重新转换。
    如果你备份好数据了,那我们开始吧。我转换的思想是:将所有的文本文件的编码改为utf8,再建立新的charset为utf8的数据库。
            首先,要把o-blog使用的所有文本文件的编码改为utf8,这里所说的文本文件包括o-blog所有的php和模板文件中的html、css文件。上网搜索了一下,可以选择的工具有UltraEdit和EditPlus。不过我使用的是EditPlus。将一个打开,再选择另保存为,再覆盖原来的文件就可以了。在此过程,可能有些文件的编码无法保存为utf8,可以先不管。   
          下面开始修改文件。
           打开 admin/class/mysql.php,找到下面的这一行
          mysql_select_db($dbname);
         在其前面加入以下代码:   
          if($this->version() > '4.1') {
       mysql_query("SET NAMES 'utf8'");
              mysql_query("SET CHARACTER_SET_CLIENT=utf8");
              mysql_query("SET CHARACTER_SET_RESULTS=utf8");
      } else        
    if($this->version() > '5.0.1') {
          mysql_query("SET sql_mode=''");
    }  
            使用EditPlus菜单“查找”下的“在文件中查找”对话框查找charset=gb2312,其中文件夹选择o-blog所在的目录,这样可以省很多的功夫.找到后把charset=gb2312替换为charset=utf-8.      
            其次要修改原来install.php文件
            把 TYPE=MyISAM 替换为 ENGINE=MyISAM  DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci。
            然后在你的空间中运行install.php,进行新的安装,如果你使用的数据库和原来的那个相同,我特别要提醒你,使用的表的前缀必须要和原来的不同,要不然会造成数据库里面原来的数据被覆盖。
           安装结束后你可以打开o-blog来看看页面上是否出现乱码,如果出现了乱码,你得查看你使用php文件和模板文件的编码是否为utf8. 如果显示的文字,还未算转换成功。由于o-blog里面使用的切割字符串函数并不是用来切割utf8字符集,在切割得出的字符串中最后一个汉字的编码很有可能不完全,这样在网页的源代码中看到的所有中文是乱码。下面要打开admin/functions.php查找 “cn_substr”函数,大概在272行,在其前面加入以下函数:
    // 用来避免 utf8 乱码
    function utf8_trim($str) {
        $len = strlen($str);
        for($i=strlen($str)-1;$i>=0;$i-=1){
            $hex .= ' '.ord($str[$i]);
            $ch   = ord($str[$i]);
            if(($ch & 128)==0)    return substr($str,0,$i);
            if(($ch & 192)==192)return substr($str,0,$i);
        }
        return($str.$hex);
    }
    前往 291 行,就会看到 return $s."...";
    在前面一行加入调用utf8_trim的以下代码
    $s = utf8_trim($s);
    这样的做法存在冗余的代码,不过这样做是最为简单的,希望风色可以进行改进。
          按照网上的说法,还要修改函数htmlspecialchars,把原来的用法
          $s=htmlspecialchars($s);
          改为 $s = htmlspecialchars($s,ENT_QUOTES,"UTF-8");
          我修改了一部分就没有修改了,因为我发现blog已经没有乱码问题了,查看数据库里面的内容,挺很正常。所以我也不知道那个修改有没有用了,有兴趣的网友可以试试看。
    不知道你们转换怎么样了呢?我的可以正常运行了。
           下面还有一个问题,怎么样把原来的数据导入到里面去。我想到了两个解决的方向。
    第一、后台里面的数据的导入导出。导入的数据会转换为gb2312,这是与现在使用utf8冲突的,这就需要修改现在代码,把原来备份的数据导进去。我没有深入了解那部分的代码,所以我不知道怎么修改,解决了导入,还要解决导出的问题。
    第二、在另外一个博客程序cblog中,有把o-blog转换为cblog的程序,可以把gb2312编码的数据转换为utf8并插入到现在使用的数据库里面去。可能修改一下代码就可以拿来用了。可是这部分我也没有研究,我的日志比较少,基本上已经手动输入到现在使用的博客里面去了。
            希望风色或者longbill研究一下,怎么处理好数据的导入导出这部分,更加希望拥有新版本的o-blog。
            如果文章中还有遗漏的地方,请提出来,我边修改边测试的,当时没有作记录,现在也是考记忆来写这篇文章了。
            我在写这篇文章的时候,longbill也处理好转换为utf8的问题了,呵呵,恭喜!

  • » 阅读全文...