避免乱码的方法通常是:php页面和mysql字符集统一、查询前用“set names utf8”
我一直是这样做,但是不知道为什么。
因为我从php发给mysql 的中文,不都是符合php所使用的编码规则的二进制串吗?那我管mysql的编码是什么呢?只要我取出来还是这个串,在php中就不会是乱码啊。然后我了一个试验:
(1)一个php页面往某表里插中文
(2)一个php页面从这个表里取插入的中文
(3)表是utf-8的,俩php页面是gb2312也就是我在gb2312的php页面,往utf8的表里插值、取值。
结果是,在查看这张表的时候,确实中文是乱码。然后取出到php页面时,就能正常显示中文了。
这也应验了我刚才的猜测。但我后来在取值的php页面上用了“set names utf8”,取出来的中文就是乱码了。让我百思不得其解。
我知道set names utf8是用来指定php和mysql交互的字符集的,但是它只要传过来的还是我插进去的那个二进制串,就不应该出现乱码啊?这是为什么呢???望大家指教!!!

解决方案 »

  1.   

    你的页面是gbk编码啊。以 set names utf8 取出来的数据当然就乱码了。
      

  2.   

    不知道我这样理解对不对啊:只要保证页面的编码和数据的编码一致,就可能避免乱码的情况:就像有时数据在数据库里看是乱码(其实数据库编码:utf-8),但写入的编码是gbk,在数据库中查看会是乱码,但读出来就不是乱码了,页面的编码也是GBK:
      

  3.   

    不用加set names utf8,如果非要加:set names GBK
      

  4.   

    恩恩 就是这个道理,你再试试用set  names  GBK ;就知道对不对了
      

  5.   

    要解决PHP中文乱码最好最快的解决办法就是:页面申明的编码与数据库内部编码一致,如果页面申请的页码与数据库内部编码不一致时,就设定连接编码mysql_query(”SET NAMES XXX”); XXX为连接编码。一定可以解决乱码的问题。
    在mysql+php程序开发中,总结了产生乱码原因:mysql数据库默认的编码是utf8,如果这种编码与你的PHP网页不一致,可能就会造成MYSQL乱码. MYSQL中创建表时会让你选择一种编码,如果这种编码与你的网页编码不一致,也可能造成MYSQL乱码. MYSQL创建表时添加字段是可以选择编码的,如果这种编码与你的网页编码不一致,也可能造成MYSQL乱码. 用户提交页面的编码与显示数据的页面编码不一致,就肯定会造成PHP页面乱码. 如用户输入资料的页面是big5码, 显示用户输入的页面却是gb2312,这种100%会造成PHP页面乱码. PHP页面字符集不正确. PHP连接MYSQL数据库语句指定的编码不正确. 
      

  6.   

    非常感谢大家的回答!!!
    但麻烦大家仔细看下我的问题,我问的不是如何避免出现乱码~我第一句我就说了吗“避免乱码的方法通常是:php页面和mysql字符集统一、查询前用set names utf8”麻烦大家别再回答有关如何避免出现乱码的问题了。再次感谢大家对我问题的回答!!!:)
      

  7.   

    但是不管我set names 什么编码,取出来的值不都是我存进去时那一串二进制码吗???
      

  8.   

    1,Mysql的配置里:CONNECTTION/CLIENT/RESULT编码一定要一致,SERVER编码无所谓。
    2,PHP文件内的字面常量字符串一定要和Mysql的CONNECTTION/CLIENT/RESULT编码一致。
    3,输出到HTML页面的Content-Type一定要和CONNECTTION/CLIENT/RESULT编码一致。
      

  9.   


    mysql相信你的配置,懂吗。你配置CLIENT/CONNECTION/RESULT都是UTF8,那么它就相信你传给它的数据都是UTF8编码的,它不会识别它们,在它眼里只有字节流,而且它确信特殊字节,比如:',NULL,\之类的字符都被\转义过,这样它就可以编码无关的识别SQL命令了,到这里为止,它不会做任何转换,记住。然后MYSQL有个SERVER编码,或者说数据库的表有编码,那么MYSQL这时候会依据CONNECTTION/CLIENT编码向存储编码进行转换,数据就那么存在数据库里了,等你查询的时候,它又会做一次转换,从存储编码转向RESULT编码,所以CONNECTTION/CLIENT/RESULT三者统一就OK了,并且保证PHP的确传递的是UTF8编码数据。
      

  10.   

    其实从C语言角度,如果你喜欢钻研这些程序的实现的话,你就可以加速你对编码的理解,程序是人写的,如果你打算写一个MYSQL,你会怎么做,结果不言而喻。
      

  11.   

    楼上审题都不够严格...我以前的帖子说过好多次了....ok, 你的情况:gbk页面插入数据到utf8表,然后取出到gbk页面首先, 这个set names x等价于
    SET character_set_client = x;
    SET character_set_results = x;
    SET character_set_connection = x;
    而这3个设置决定了不同阶段的字符集------------------------------------如果不加set names utf8
    一般缺省情况下这3个设定都是latin1,你可以用show VARIABLES like 'character_set%'看一下ok,这时,
    字符集的变化情况是
    gbk(输入页面)->latin1(character_set_client)->latin1(character_set_connection)->utf8(数据库)->latin1(character_set_connection)->latin1(character_set_results)->gbk(输出页面)比如你输入一个"严"
    "D1CF"(输入的一个gbk字符,被解释为2个latin1字符,因为你的client是latin1)
    =>"D1""CF"(2个latin1字符ÑÏ)
    ->"c391""c38f"(2个utf8字符,进db,注意这时是4个字节,2个字符)
    ->"D1""CF"(2个latin1字符ÑÏ)
    没了....嗯?为啥没了还能在页面上看到正确的汉字"严"???如果你在页面上"查看源代码", 你会看到那是"乱码"(latin字符)
    这个是因为html页面是流方式输出到浏览器,浏览器只知道接受一串字符过来,然后根据你指定的编码,比如<meta http-equiv="Content-Type" content="text/html; charset=gbk"/>
    来分析显示字符,注意2个latin1字符D1CF和一个gbk汉字严在二进制下是无法区分的,所以它就解释其为汉字,
    如果你charset=ISO-8859-1了,它就变"乱码"了-----------------------------------------------------------------好, 这下来说set names utf8后, 就是
    set character_set_client = utf8;
    set character_set_results = utf8;
    set character_set_connection = utf8;那么,字符集变化为
    gbk(输入页面)->utf8(character_set_client)->utf8(character_set_connection)->utf8(数据库)->utf8(character_set_connection)->utf8(character_set_results)->gbk(输出页面)那么"严"的变化为
    "D1CF"(输入的一个gbk字符,因为你client是utf8....被当成utf8字符)
    ->但是...好像不是合法的utf8字符....所以...(这步我没测试,到底转成了什么我也不知道)
    ->"乱码"(?个utf8字符)(存入数据库)
    ->"乱码"(原样取出并传到客户端,因为db和results都是utf8)
    页面上就更是乱码了,而且无法变化页面字符集来得到正确的汉字----------------------------------------------------------所以,很多人都知道,你的这个情况应该set names gbk,就是
    set character_set_client = gbk;
    set character_set_results = gbk;
    set character_set_connection = gbk;那么,字符集变化为
    gbk(输入页面)->gbk(character_set_client)->gbk(character_set_connection)->utf8(数据库)->gbk(character_set_connection)->gbk(character_set_results)->gbk(输出页面)那么"严"的变化为
    "D1CF"(输入的一个gbk字符,因为你client是gbk,所以被正确解释成gbk字符)
    ->"e4b8a5"(一个utf8字符,进db,注意这时是3个字节,1个字符)
    ->"D1CF"(转回正确的gbk字符)
    这时你"查看源代码",应该也是正确的字符"严"---------------------------------------------------------应该足够明白了吧, 所以我经常让人用length和CHAR_LENGTH测数据库里的字符串的字节数和字符数,
    大体可以知道保存的字符是否正确嗯,有问题欢迎再探讨
      

  12.   

    看了楼上的回复再补充几句:
    character_set_client / character_set_results / character_set_connection 
    这几个mysql既然放在不同的设置变量里,它们是完全可以设置成不同的字符集的,虽然我们很多时候都不需要. 1)这几个是基于连接,所以set names要放在connect之后,
    你完全可以让不同的客户端使用不同的client/results,比如一个人gbk连上来,一个人big5连上来,他们可以分别看见gbk/big5的页面2)你可以完全可以client设成gbk, results设成big5,
    这样你可以发送gbk字符串到服务端,存utf8进db,再big5输入....(当然,可想而知这个应用比较特别)3)你的编码必须兼容,不同的编码包含不同的字符,在字符从一个集转向另一个集的情况,目标集没有的字符会变成?,这个是不可逆的
    比如你不能cient/result/db是utf8,然后connection是latin1....这样因为汉字在latin1里都是不存在的,会全部变成?,然后也变不回来了
      

  13.   

    helloyou0说的就是原理了,我给楼主的解答是告诉楼主统一起来一切都变得简单可控。
      

  14.   

    本帖最后由 PhpNewnew 于 2012-06-16 10:24:04 编辑
      

  15.   

    楼主的这个理解是正确的,数据库不会也不应该去主动改变存储进去的内容
    放进去的是什么,拿出来的就是什么!
    至于数据在数据库是如何存放的,就不是我们需要考虑的了。这就是问什么我们选择使用数据库系统而不是文件系统的原因。
    引入字符集的原因在于,我们不仅仅是在数据库里简单的存放数据,还需要通过数据库进行检索和排序
    由于不同的字符集的检索和排序的规则是有所区别的,所以需要制定字符集。这就是所谓的“二进制可靠”
    另外,存放在数据库中的内容是给大家使用的,有人需要utf-8字符集,有人需要gbk字符集,但是你并不可能对同一内容去保存多个字符集版本。
    你只需通过 set names 通知一下 mysql 现在使用什么字符集进行交互就可以了
    字符集的转换工作就由 mysql 来完成了
      

  16.   

    多谢你细致的回答!!!
    但我对其中还是有点不太明白,这段:
    比如你输入一个"严"
    "D1CF"(输入的一个gbk字符,被解释为2个latin1字符,因为你的client是latin1)
    =>"D1""CF"(2个latin1字符ÑÏ)
    ->"c391""c38f"(2个utf8字符,进db,注意这时是4个字节,2个字符)
    ->"D1""CF"(2个latin1字符ÑÏ)“严”字在第一次被解释成latin1的时候,被翻译成了字符ÑÏ,但是它底层的值还是D1CF。
    那为什么到入db,被解释成utf8的时候,就改变它的底层值编程4个字节了呢?而刚才解释成latin1的时候是没有改变底层值的啊。
      

  17.   

    你没看出他是在忽悠你吗
    比如你输入一个"严"
    "D1CF"(输入的一个gbk字符,被解释为2个latin1字符,因为你的client是latin1)
    不是“解释为”而是当做
    由于表是 utf8 的,所以在入库时 mysql 要做 latin1 到 utf8 的编码转换,出库时 mysql 要做 utf8 到 latin1 的编码转换
    于是,放进去什么,拿出来还是什么
      

  18.   

    终于搞明白了!多谢各位!!!尤其感谢helloyou0兄!还有xuzuning兄和qq120848369兄!!!