http://www.lovelucy.info/utf8-vs-utf-8.html#more-794

一、遇到的问题

曾经被字符集间复杂的转换搞怕了,正好新项目要求国际化,需要能够显示多种语言,于是一开始就规定统统使用 UTF-8 编码。

  1. 所有代码文件使用 UTF-8 编码存盘
  2. MySQL数据库所有表,所有字段设置 Collation (中文翻译为“整理”?)属性为 “utf8_general_ci”
  3. 所有页面输出
    <meta http-equiv="content-type" content="text/html; charset=UTF-8">

即便是这样,PHP 从数据库中读取内容,显示到网页上,还是出现了乱码,英文没问题,中文统统都是?问号。这样也行?艰苦卓绝的 debug 开始了……

二、调查原因

MySQL 的字符集以繁多而著名,而其默认又是 latin1 的瑞典语编码,数据导入导出的时候一不留神就乱码了。

参考以上链接的官方文档,总结之:MySQL 对于字符集的支持细化到四个层次:

  1. server 服务器级
  2. database 数据库级
  3. table 表级
  4. connection 连接级

确保每一个级别都是使用的 UTF-8 编码。检查了一下,貌似我没有设置 connection 连接级。前 三种字符集级别只是规定了数据存储在 MySQL 中的编码格式,客户端读出数据后完全可以按照自己的意愿来解读数据。最后的 connection 连接级就是规定了客户端以什么编码来解析读取到的数据。也就是说,不论是 php 代码还是 DB 管理软件,在从 MySQL 读取数据之前都需要设定自己作为客户端的编码格式。

好吧,那么,在任何查询执行之前,先执行一句 set names utf-8。(使用框架进行开发的话,大多数框架应该会自动完成这一步,程序员一般只需要改配置文件)

$conn = mysql_connect($db_host, $db_user, $db_password);if(!$conn)die("Could not connect to mysql.");mysql_select_db($db_name);mysql_query("set names 'utf-8'");

刷新页面,仍旧乱码。

三、解决

只好再继续调查。¥#$…&%=^*&+%-#!@_@ 苦逼地一天就这样过去了……

咦,等等,官方文档里写的是 set names utf8 哦,和 set names utf-8 有啥区别么?赶紧试一下。

刷新页面,我擦,正常了。

搜了一下,发现被坑的人还真不少。UTF-8应该是标准的写法,在大多数场合都是有中间那个横杠的,只是MySQL这里偏偏就非主流去掉了横杠使用UTF8。

遇到同样问题,而本文未能帮你解决的,这篇乱码总结可能会帮到你。

//以下是讨论内容

今天看到大家在讨论,发现这是个很严重而又容易疏忽的问题,我以前也一直是用set names,遂记录下来,也提醒自己一把。

应该使用 mysql_ set_ charset(); 不要使用sql query来设置,有风险。

1.set names与mysql_set_charset有什么区别?

一般情况下, 使用”SET NAMES”就足够了, 也是可以保证正确的. 那么为什么手册又要说推荐使用 mysqli_set_charset(PHP>=5.0.5)呢。手册里面也没有明确说明。我们可以看下php扩展的源代码:

//php-5.2.11-SRC/ext/mysqli/mysqli_nonapi.c line 342
PHP_FUNCTION(mysqli_set_charset)
{
MY_MYSQL *mysql;
zval *mysql_link;
char *cs_name = NULL;
unsigned int len;
if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis()
, “Os”, &mysql_link, mysqli_link_class_entry, &cs_name, &len) == FAILURE) {
return;
}
MYSQLI_FETCH_RESOURCE(mysql, MY_MYSQL*, &mysql_link, “mysqli_link”, MYSQLI_STATUS_VALID);
if (mysql_set_character_set(mysql->mysql, cs_name)) {
//** 调用libmysql的对应函数
RETURN_FALSE;
}
RETURN_TRUE;
}
可以看到php的mysql扩展是直接调用了mysql的mysql_set_character_set函数,接下来看看mysql的代码

//mysql-5.1.30-SRC/libmysql/client.c, line 3166:
int STDCALL mysql_set_character_set(MYSQL *mysql, const char *cs_name)
{
struct charset_info_st *cs;
const char *save_csdir= charsets_dir;
if (mysql->options.charset_dir)
charsets_dir= mysql->options.charset_dir;
if (strlen(cs_name) < MY_CS_NAME_SIZE &&
(cs= get_charset_by_csname(cs_name, MY_CS_PRIMARY, MYF(0))))
{
char buff[MY_CS_NAME_SIZE + 10];
charsets_dir= save_csdir;
/* Skip execution of "SET NAMES" for pre-4.1 servers */
if (mysql_get_server_version(mysql) charset= cs;
}
}
//以下省略
可以看到,除了调用real_query设置set names,还设置了mysql的charset变量。

2.这样有什么影响?

mysql_real_escape_string会受到影响,它与mysql_escape_string的区别就 是, 它会考虑”当前”字符集。如果仅仅使用set names,mysql_real_escape_string可能会失效。

例子:

$mysqli = new mysqli(“localhost”, “user”, “pass”, “test”, 3306);

/* check connection */
if (mysqli_connect_errno()) {
printf(“Connect failed: %s\n”, mysqli_connect_error());
exit();
}

$mysqli->query(‘SET NAMES gbk’); //使用set names设置字符集
$city = chr(0xbf).chr(0x5c); //0xbf5c是个有效的gbk字符,模拟用户输入
$city = $mysqli->real_escape_string ($city);//使用real_escape进行过滤

/* this query will fail, cause we didn’t escape $city */
if (!$mysqli->query(“INSERT into myCity(name) VALUES (‘$city’)”)) {
print “INSERT into myCity (name) VALUES (‘$city’)\n”;
printf(“Error: %s\n”, $mysqli->error);
}

var_dump($city);

var_dump($mysqli->client_encoding());

$mysqli->close();
3.解决方案

mysqli_set_charset函数对PHP和Mysql有版本要求,必须当mysql版本大于5,PHP版本大于5.0.5时,此函数才有 效。至于另一个mysql_set_charset函数,则更要求PHP版本大于5.2.3时才能有效。对于mysql4.1以上版本,使用”SET character_set_client=binary;”
推荐使用mysql_set_charset设置字符集的方案,只有在环境不允许的情况下,我们才推荐使用第二种binary编码的方案。但是无论在什么情况下,都禁止使用”SET NAMES”来作为设置字符集的操作。

转载于:https://www.cnblogs.com/xiaohong/archive/2012/03/13/2393327.html

转乱码UTF8和UTF-8网页编码相关推荐

  1. 爬取网页时自动获取网页编码信息,并对特殊的乱码页面(压缩过的网页内容)用gzip进行解码。...

    gzip的命名空间引用如下:using System.IO.Compression; 获取网页编码和信息 /// <summary>         /// create time 201 ...

  2. html设置页面编码gbk,GBK及UTF-8网页编码定义与应用

    网页编码英文译为web page encoding,是在网页中指定其特定的字符编码格式的库. GBK是国家标准GB2312基础上扩容后兼容GB2312的标准.GBK的文字编码是用双字节来表示的,即不论 ...

  3. 浏览器正确理解和使用GBK及UTF-8(UTF-8 + BOM)网页编码

    网页编码英文译为web page encoding.是在网页中指定其特定的字符编码格式的库. GBK是国家标准GB2312基础上扩容后兼容GB2312的标准. GBK的文字编码是用双字节来表示的.即不 ...

  4. Chrome网页编码显示乱码

    今天打开Chrome浏览器,网页编码显示乱码了,这还是第一次遇到这样的情况 解决办法: 第一步  在chrome网上应用店下载  Set Character Encoding 这是下载地址: http ...

  5. 解决Chrome网页编码显示乱码的问题

    解决Chrome网页编码显示乱码的问题   记得在没多久以前,Google Chrome上面出现编码显示问题时,可以手动来调整网页编码问题,可是好像在Chrome 55.0版以后就不再提供手动调整编码 ...

  6. java中html中文乱码怎么解决_Java读取网页HTML 汉字乱码 (已解决,bufferedReader中编码改成...

    Java读取网页HTML 汉字乱码 (已解决,bufferedReader中编码改成 Java读取网页HTML 汉字乱码 (已解决,bufferedReader中编码改成跟网页的一致即可) #网页HT ...

  7. 前端页面乱码,设置了utf-8,检查了浏览器编码还是出现乱码

    写项目后台管理的时候,原本正常显示的页面加了两行代码,页面突然变成了乱码,我以为是我那两行代码的问题,后来把代码删了,还是乱码,数据库查出来的所有数据都是可以正常读取出来的.但是页面上写死的中文全部出 ...

  8. 怎么把html编码变成gb2312,如何修改网页编码gb2312与utf-8

    网页编码一般gb2312或者utf-8比较流行,对于中国大陆的大部分浏览器而言,编码为gb2312都能识别,而加上国外的浏览器来说,可能utf-8更受欢迎,暂且定utf-8编码为通用编码吧,所以有时候 ...

  9. 彻底搞懂编码ASCII、Unicode、GBK 和 UTF8 、UTF-16、UTF-32编码方式(非常经典)

    GBK,ISO-8859-1,GB2312的本质区别 编码有几种 ,计算机最初是在美国等国家发明的 所以表示字符只有简单的几个字母只要对字母进行编码就好 我们标准码 iso-8859-1 这就是一个标 ...

  10. UTF8和UNICODE和GBK编码

    UTF8并不算是一种电脑编码,而是一种储存和传送的格式,如前所述,每个Unicode/UCS字符都以 2或4个bytes来储存,看看以下的比较: 以"I am Chinese"为例 ...

最新文章

  1. 高糊视频秒变4K,速度快了9倍!东南大学提出新的视频超分辨率系统
  2. 利用HttpModuler实现WEB程序同一时间只让一个用户实例登陆
  3. 剑指 Offer 11. 旋转数组的最小数字 简单
  4. Class.isAssignableFrom(Class clz)与instanceof与Class.isInstance(Object obj) 的区别和联系
  5. AJAX代码示例(不使用AJAX控件)
  6. Music Notes(前缀和+二分)
  7. SP2-0618: Cannot find the Session Identifier. Check PLUSTRACE role is enable
  8. 被调用的对象已与其客户端断开连接
  9. javascript引用bug带来的继承
  10. 软件质量的理解 摘录
  11. 美国高级情报研究计划局(IARPA)发起公共安全问题预测机器学习挑战赛(总奖池10万美金)...
  12. 代码生成利器-NCodeGenerate 教程(2) NCodeGenerate的代码公用之一
  13. iOS核心动画CALayer和UIView
  14. 在线订餐系统php心得体会_基于php的网上订餐系统的设计与实现论文.doc
  15. libgdx之瓦片地图(TiledMap)
  16. linux内核的裁剪与移植
  17. linux中fdisk的参数,Linux fdisk命令参数及用法详解---Linux磁盘分区管理命令fdisk
  18. 使用场景法对在线购网站编写的用例示范
  19. gif透明背景动画_如何利用premiere制作GIF动态图片
  20. python二维数组的定义方式

热门文章

  1. 字符串数组(就自己做个笔记)
  2. java模拟使用接口,关于java:模拟一个类与模拟它的接口
  3. 景德镇陶瓷学院计算机协会,景德镇陶瓷学院计算机协会换届大会总结报告
  4. python迷宫问题求最短路径_用栈求解迷宫问题的所有路径及最短路径程序
  5. mysql 导出中间 数据_MYSQL数据库之间的数据导出与导入
  6. MySQL面试题 | 附答案解析(十三)
  7. 使用Python,OpenCV线程化方式提高视频FPS(每秒帧数)
  8. 使用Python,OpenCV加载图像并将其显示在屏幕上?
  9. python建站与java建站有何不同_详解模板建站和定制建站的不同之处
  10. android view设置按钮颜色_Android 主题换肤技术方案分析