最近刚刚才接触wamp 遇到乱码问题。费了好大的气力才解决!问题分析,希望对大家有用
php和mysql涉及到的字符有php前端页面字符集,mysql数据库字符集,和连接字符集。
1.php前端页面字符集。
php文件中的html脚本字符编码通过<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>进行设置,故html使用的编码就是utf8
另外我们知道每个文件本身都有自己的编码,将文件另存为需要的编码。一般要与页面的html编码一致,故可以将文件编码设置utf8。因为php经常
要应用js文件,如果js中的文件编码与php文件的编码不一直,那么js文件的中文汉字引用到php文件中会出现乱码。故js文件的编码要与php文件的
编码和html脚本编码一直。这样浏览器解析的时候不会出现乱码。
2.mysql数据字符集编码。
Mysql的字符集里有两个概念, 一个是“Character set(字符集)”,另一个是“Collations”(字符序)。
查看mysql字符集编码通过命令 show variables like '%char%' 以及 show variables like '%coll%' 来分别查看mysql字符集和字符序的编码
2.1 mysql字符集编码有
character_set_server:默认的内部操作字符集
character_set_client:客户端来源数据使用的字符集
character_set_connection:连接层字符集
character_set_results:查询结果字符集
character_set_database:当前选中数据库的默认字符集
character_set_system:系统元数据(字段名等)字符集
mysql默认字符集为latin1,但可以通过在mysql配置文件my.ini中通过在[client]下添加default-character-set = utf8 设置成所需要的编码。
mysql数据库字符集主要包含几层概念,分别是数据库级别的字符集,数据表的字符集和表中字段的字符集。默认情况下,三个字符集都是从大到小继承的关系。默认字符集是character_set_server的字符集。
2.2 mysql字符集转换过程
character_set_client =>character_set_connection=>character_set_results
例如,想数据表插入utf8的字符,如果采用默认字符集(latin1)。而数据表字段编码为(gbk)。故utf8字符集从在客户端传个mysql服务器,而mysql的character_set_client表示希望得到什么样的字符集,而接受到是utf8,故mysql将其首先转码成latin1的编码,而character_set_connection是latin1,故编码不变。最后将字符存入为gbk的编码,故将latin1的字符集最后有换成gbk。故存入为乱码。
继续解析:utf8用3个字节表示一个汉字,经过mysql服务器的转换就转换成了3个latin1的字符。因为latin1有一个字节编码。最后存入数据表的时候,又将3个现在是latin1的字符转换成GBK,而GBK是有两个字节进行字符编码,但由于latin1的字符是一个字节表示,故GBK就另外自己加了一个字节来组成两个字节来转换编码,故存入了3个转换后字符,乱码出现。
读取方式类似插入的逆过程。
3.php和mysql乱码解决
首先查看mysql数据库的字符集编码,然后设置php连接mysql的字符集方式,尽量两者保持一致。
PHP通过设置character_set_client,告诉Mysql,PHP存进数据库的是什么编码方式。
PHP通过设置character_set_results,告诉Mysql,PHP需要取什么样编码的数据。
PHP通过设置character_set_connection,告诉Mysql,PHP查询中的文本,使用什么编码。
那么PHP如何设置呢? 即通过mysql_query(“set names utf8”);如果采用CI框架,则在config下面的database.php里面设置char_set。
即首先数据建表时采用的是utf8,通过mysql_query来设置php连接mysql的方式,也采用utf8,而且页面html是utf8。则乱码将不会出现。
但是,事情往往事与愿违,可能我们只是负责页面的设计,而采用别人已经建立好的数据库,就无法保证一致的字符集。
很多人在建立数据库的时候都采用了默认latin1的字符集,这样里面的中文字段是字符集默认为GBK(这个还不太明白,为什么是GBK)。
而PHP在制作html页面的时候采用的是通过的utf8编码。 这样查询出来的结果就会是乱码。
不过没关系,尽管数据库采用的默认字符集,但我们依然要使用mysql_query来进行设置连接字符集与默认字符集保持一直。
故将其设置为latin1。这样,字符集在经历client , connection, results的时候就保持一值,不会出现转换。例如,数据库都是默认字符集latin1,
在默认下,中文字段GBK。而连接方式的字符集设置是latin1,故数据表的数据传输就不会发生转换,因为里面的都是latin1的方式传。
最后在php页面,故接受到的中文就是GBK的中文,而php一般中文字符都采用utf8的编码。
那么我们只需要将查询出来的结果转换成utf8 即可。
查询过程:
如 采用iconv和mb_convert_encoding转换 $result = iconv("gbk","utf8//IGNORE",$result); iconv第一个参数为源编码,第二个为目标编码
$result= mb_convert_encoding( $result,"utf8","gbk"); mb_convert_encoding第二个参数目标编码,第三个为源码。
尽管mb_convert_encoding的函数效率问题较低,但是它屏蔽了iconv的一些bug。有时候采用iconv转换字符时,会出现Wrong set 不能转换的问题。
使用mb_convert_encoding可以解决。 如我出现过GBK无法与utf8转换的问题,用mb_convert_encoding解决了。
插入过程:
就是将页面输入的utf8的字符转换成GBK的字符,然后执行sql插入。如插入数据库的时候也无乱码。
两者结合就可以保证查询和插入,修改时,页面和数据库都无乱码。
关键是保证连接字符集和数据库的字符集保持一直。这样可以保证mysql内部的多种字符集无转换。只要进行数据表字段和页面字符集间的转换即可。
笔者是新人,记录下自己的总结。都是文字描述,请谅解!而且自己对字符集的问题,依然有理解上的问题。如果写错了,请包容!~
继续努力学习!~~