PHP中UTF-8的困扰,还有可恶的BOM..

序言:
前些日子,公司发邮件周刊,部分使用Windows English OS 的人反映,他们Outlook收到的是乱码,才意识到自己使用的是GB2312编码,而非国际ISO标准的UTF-8,马上改进,用Microsoft OS 自带的Notepad 直接另存为UTF-8编码,然后PHPMailer 测试发送给自己! 我靠,NND,什么东西,超级乱码,以为自己在PHPMailer里的编码设置错了,立刻检查!发现没错,多次更改测试,还是不可以! 怀疑编辑器有问题,立刻更换更强悍的UltraEdit,果然, 是Notepad另存为的时候,自动生成了BOM码在里面,我靠………. …………..

今天,在喜悦村(www.phpx.com)闲逛,看到一位仁兄的帖子,谈到了PHP中UTF-8的问题,哈,正好拿来复习复习,多谢这位仁兄了啊!以下是部分内容!


导言:

  • 什么是UTF-8
  • UNICODE,GBK,UTF-8区别
  • 什么是BOM
  • 关于UTF-8
    UTF-8是unicode编码的扩展(也可以说是子集:Unicode Translation Format),由Ken Thompson于 1992年创建,只要将某个字符的unicode编码一一插入相应的空位(刚好有16个空位)就可以成为一个UTF-8编码! 详情见(http://hi.baidu.com/itezone/blog/item/8d9ca35200c18b0c0df3e336.html)

    关于 BOM (浏览器对象模型(Brower Object Model))
    这里有,我不敖述了!http://baike.baidu.com/view/126558.htm

    UNICODE,GBK,UTF-8区别
    http://www.phpchina.com/42113/viewspace_16547.html
    言规正传
    1、编辑器:
    不要使用任何微软的编辑器,什么Frontpage,Web Designer,记事本,写字板什么的,能丢的全部丢开,因为这些编辑器会在你的UTF-8文档前面产生BOM,关于BOM的具体说明,可以在 这里 找到,当初我直接拿记事本转UTF-8覆盖原文件,造成………….,至今记忆犹新。
    2、MySQL数据库:
    注意建库,建表,建字段(注意有三处)的时候,都要选用utf8_general_ci的整理格式(Collation),在PHP使用mysql_connect()函数连接数据之后,需要加上一句:
    mysql_query(‘set names “utf8″‘);
    3、PHP:
    使用mbstring库,不要使用iconv库。
    使用preg而不要使用ereg来处理字符。
    使用htmlentities()函数,html_entity_decode()函数的时候要带上第三个参数:

    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
    <?php
    $str = "<a href='test'>中文</a>";
    echo htmlentities($str,ENT_COMPAT,"UTF-8"); //显示(源代码里面) <a href='test'>涓枃</a>
    echo html_entity_decode(htmlentities($str,ENT_COMPAT,"UTF-8"),ENT_COMPAT,"UTF-8"); // 显示(源代码里面) <a href='test'>中文</a>
    ?>

    这里再给出一个匹配UTF-8中文字符的正则表达式:

    <meta http-equiv="Content-Type" Content="text/html; charset=utf-8">
    <?php
    $word = "中文";
    if (preg_match("/^(&#91;".chr(228)."-".chr(233)."&#93;{1}&#91;".chr(128)."-".chr(191)."&#93;{1}&#91;".chr(128)."-".chr(191)."&#93;{1}){1}/",$word) == true || preg_match("/(&#91;".chr(228)."-".chr(233)."&#93;{1}&#91;".chr(128)."-".chr(191)."&#93;{1}&#91;".chr(128)."-".chr(191)."&#93;{1}){1}$/",$word) == true || preg_match("/(&#91;".chr(228)."-".chr(233)."&#93;{1}&#91;".chr(128)."-".chr(191)."&#93;{1}&#91;".chr(128)."-".chr(191)."&#93;{1}){2,}/",$word) == true)
    {
    echo "很好,这是一个UTF-8编码的汉字";
    }
    else
    {
    echo "抱歉,这不是一个UTF-8编码的汉字";
    }
    ?>

    4、HTML:在标签对里面加上

    <meta http-equiv="Content-Type" Content="text/html;charset=utf-8" />

    5、JS:JS的问题比较复杂,如果直接将文件存为UTF-8的编码,那么当用户在直接用浏览器访问这个页面的时候(也许某些程序员会这么做),浏览器可能会使用其它的编码去读取这个文件而造成其中的UTF-8中文乱码,当然,这并不会影响到程序的运行。在加载JS的时候,可以说明一下载入JS的编码,当然,如果已经在HTML头里面声明了编码,这里就不是必须的了:

    JS要注意的另一个问题是他的escape()函数,在ECMAScript v3中,escape( ) 会被剔除,建议使用encodeURI( )和encodeURIComponent( )。这可以帮助你远离escape()函数引起的乱码问题。
    6、CSS:在CSS文件的头部加上这行代码:
    @charset “UTF-8”;

    7、URL:为了让URL变得更为友好,许多PHP程序员喜欢让URL显示文字而不是URL编码,目前较为合理的解决方案是将GET方法发送的数据转为GBK编码,然后再接受这些数据,如果你希望使用UTF-8直接友好的GET数据,你会在使用PHP的$_GET数组时遇到一些问题。
    8、Email:使用UTF-8编码的字符发送邮件,也是一件让人头疼的事情,理想的方法是将编码转变为GBK,然后再发送。
    9、Ajax:使用POST的方式发送数据,不要使用GET的方式,不然无法成功发送部分UTF-8中文字符。

    关注公众号,手机阅读更方便。程序员的阅微草堂:

    知识共享许可协议莿鸟栖草堂CFC4N 创作,采用 知识共享 署名-非商业性使用-相同方式共享(3.0未本地化版本)许可协议进行许可。基于http://www.cnxct.com上的作品创作。转载请注明转自:PHP中UTF-8的困扰,还有可恶的BOM..

    6 thoughts on “PHP中UTF-8的困扰,还有可恶的BOM..

    1. 没有看懂你那是怎么匹配UTF-8中文的,前段时间偶JAVA里也遇见乱码问题
      俺同学的一个波导什么型号的手机,看小说的时候没有乱码,很一致,都是小方块!
      import java.util.regex.Matcher;
      import java.util.regex.Pattern;

      public class FindChinese
      {
      public static void main(String[] args)
      {
      String f = “欢迎welcome to光临 wmdly,纯音乐部落,www.chunmusic.cn,谢谢!”;
      Pattern p = Pattern.compile(“[\\u4E00-\\u9FFF]+”);
      Matcher matcher = p.matcher(f);

      StringBuffer sb = new StringBuffer();
      while (matcher.find())
      {
      sb.append(matcher.group());
      }
      System.out.println(sb);
      }
      }
      ==================================
      Pattern p = Pattern.compile(“[\\u4E00-\\u9FFF]+”);
      这个貌似也能匹配中文,不晓得和中文UTF-8匹配有什么区别。
      ==================================

      国际化问题确实有很多让人郁闷的地方
      不过用UTF-8,再加上资源文件,貌似什么问题都没有哦
      比如
      把中文弄成这个样子\u9648\u9a70\u554a\uff1f\u8fd8\u597d\u554a\uff1f

      o(∩_∩)o…哈哈^_^鲁班门前刷大斧头了哦啊哈…………

    2. 没有看懂你那是怎么匹配UTF-8中文的,前段时间偶JAVA里也遇见乱码问题
      俺同学的一个波导什么型号的手机,看小说的时候没有乱码,很一致,都是小方块!
      import java.util.regex.Matcher;
      import java.util.regex.Pattern;

      public class FindChinese
      {
      public static void main(String[] args)
      {
      String f = "欢迎welcome to光临 wmdly,纯音乐部落,www.chunmusic.cn,谢谢!";
      Pattern p = Pattern.compile("[\\u4E00-\\u9FFF] ");
      Matcher matcher = p.matcher(f);

      StringBuffer sb = new StringBuffer();
      while (matcher.find())
      {
      sb.append(matcher.group());
      }
      System.out.println(sb);
      }
      }
      ==================================
      Pattern p = Pattern.compile("[\\u4E00-\\u9FFF] ");
      这个貌似也能匹配中文,不晓得和中文UTF-8匹配有什么区别。
      ==================================

      国际化问题确实有很多让人郁闷的地方
      不过用UTF-8,再加上资源文件,貌似什么问题都没有哦
      比如
      把中文弄成这个样子u9648u9a70u554auff1fu8fd8u597du554auff1f

      o(∩_∩)o…哈哈^_^鲁班门前刷大斧头了哦啊哈…………

    3. 没有看懂你那是怎么匹配UTF-8中文的,前段时间偶JAVA里也遇见乱码问题
      俺同学的一个波导什么型号的手机,看小说的时候没有乱码,很一致,都是小方块!
      import java.util.regex.Matcher;
      import java.util.regex.Pattern;

      public class FindChinese
      {
      public static void main(String[] args)
      {
      String f = &quot;欢迎welcome to光临 wmdly,纯音乐部落,www.chunmusic.cn,谢谢!&quot;;
      Pattern p = Pattern.compile(&quot;[u4E00-u9FFF] &quot;);
      Matcher matcher = p.matcher(f);

      StringBuffer sb = new StringBuffer();
      while (matcher.find())
      {
      sb.append(matcher.group());
      }
      System.out.println(sb);
      }
      }
      ==================================
      Pattern p = Pattern.compile(&quot;[u4E00-u9FFF] &quot;);
      这个貌似也能匹配中文,不晓得和中文UTF-8匹配有什么区别。
      ==================================

      国际化问题确实有很多让人郁闷的地方
      不过用UTF-8,再加上资源文件,貌似什么问题都没有哦
      比如
      把中文弄成这个样子u9648u9a70u554auff1fu8fd8u597du554auff1f

      o(∩_∩)o…哈哈^_^鲁班门前刷大斧头了哦啊哈…………

    4. 没有看懂你那是怎么匹配UTF-8中文的,前段时间偶JAVA里也遇见乱码问题
      俺同学的一个波导什么型号的手机,看小说的时候没有乱码,很一致,都是小方块!
      import java.util.regex.Matcher;
      import java.util.regex.Pattern;

      public class FindChinese
      {
      public static void main(String[] args)
      {
      String f = &quot;欢迎welcome to光临 wmdly,纯音乐部落,www.chunmusic.cn,谢谢!&quot;;
      Pattern p = Pattern.compile(&quot;[\\u4E00-\\u9FFF] &quot;);
      Matcher matcher = p.matcher(f);

      StringBuffer sb = new StringBuffer();
      while (matcher.find())
      {
      sb.append(matcher.group());
      }
      System.out.println(sb);
      }
      }
      ==================================
      Pattern p = Pattern.compile(&quot;[\\u4E00-\\u9FFF] &quot;);
      这个貌似也能匹配中文,不晓得和中文UTF-8匹配有什么区别。
      ==================================

      国际化问题确实有很多让人郁闷的地方
      不过用UTF-8,再加上资源文件,貌似什么问题都没有哦
      比如
      把中文弄成这个样子u9648u9a70u554auff1fu8fd8u597du554auff1f

      o(∩_∩)o…哈哈^_^鲁班门前刷大斧头了哦啊哈…………

    5. 哈,JAVA 没学过,大体看了下,你这个是匹配中文的吧! 呵呵, \\u4E00-\\u9FFF 是中文字符 在unicode编码中编码中的 区间 啊! 哈,你太谦虚了,会发胖的!

    6. 哈,JAVA 没学过,大体看了下,你这个是匹配中文的吧! 呵呵, u4E00-u9FFF 是中文字符 在unicode编码中编码中的 区间 啊! 哈,你太谦虚了,会发胖的!

    7. UTF-8签名(UTF-8 signature)也叫做BOM(Byte Order Mark),不是指浏览器对象模型(Brower Object Model)

    发表评论

    电子邮件地址不会被公开。 必填项已用*标注