首页 > 数据库编码和脚本编码的疑惑

数据库编码和脚本编码的疑惑

我数据库字段编码用的是gbk,
插入这个字段的数据也是用set names 'gbk'经过转换的,
我的php脚本是使用utf8编码。

问题是:当我取出数据库里的数据,为什么客户端能以utf8编码正确显示?按我的逻辑是,既然页面用的是utf8编码,那么数据库里取出的gbk数据应该乱码才对。

header("Content-type: text/html; charset=utf-8");
$link = mysql_connect('localhost', 'root', 'bitnami');
mysql_select_db('test', $link);
mysql_query("set names 'gbk'");

$sql = "update table set test='北京'";

mysql_query($sql);

$sql = "select * from table";

$res = mysql_fetch_assoc(mysql_query($sql));

echo $res['test'];


因为之前的回复是随着题主的提问更新而更新,所以逻辑也比较混乱,这里尝试清晰地回答一次:

  1. 数据库中的取出以 gbk 编码存储的数据。
  2. 设置 set names gbk,所以服务器知道数据的正确编码,因此可以解码得到正确的文本内容。
  3. 页面内设置 charset=utf-8,将当前页面内容以 utf-8 进行编码。
  4. 浏览器以 utf-8 解码读取页面,因此可以得到正确的文本内容。

以下为回复历史记录:

我猜测题主从数据库里取出的并不是汉字吧。因为 gbkutf-8 都是兼容 ASCII 编码的。
我们可以测试下:
新建一张表,编码为 gbk

页面内编码设置为 utf-8

现在我们存两个数据,内容为:

现在我们取出内容非汉字的 test,并打印到屏幕,结果为:

看到了吧,非乱码,那么接下来我们来打印汉字记录,结果为:

出现乱码了,现在题主应该明白了,因为两种编码对 ASCII 都是兼容的,这也就说并不是所有情况下都会出现乱码。刚好前几天总结了下编码问题,题主可以参考:《谈谈字符编码》。

根据题主更新的代码,我再做第二次测试,为了方便所以我就不做 update 操作,单纯以查询为例。
注释掉 mysql_query("set names 'gbk'");

结果为:

非注释下:

结果为:

现在我们可以确定原因在于 set names 'gbk',因为它会使编码统一。
题主如果对 set names 这个操作不太熟悉,可以稍微做下解释:
set names x 操作相当于同时做了以下三个操作:

set character_set_client = x;
set character_set_results = x;
set character_set_connection = x;

也就是说数据输出的途径为:

server→connection→results

如果你不做 set names 'gbk' 的操作,那么数据到 results 的时候,就会以默认编码方式来处理,不要考虑什么页面编码混乱问题,你的目的是为了正常显示数据,你要告诉计算机你从数据库取来的数据时以 gbk 编码的,这样计算机才能得到正确的数据。
另外题主所担心的问题实际上不存在的,设置页面显示的编码格式与 set names 'gbk' 两者是不冲突的。
你可以这样测试:

 echo mb_detect_encoding($res['test']);

输出为 UTF-8,这也就是说实际过程应该是这样的:从服务器端取来数据,因为 set names 'gbk' 操作,所以计算机才能得到真正的文本内容-“北京”,然后再按照页面的设置,将其按照 UTF-8 进行编码显示。
如果题主还有疑惑,我们可以做个更彻底的测试。
这次我们把数据库默认的编码改为 utf-8,你会发现显示的仍然是乱码,除非你做了这个操作:

`mysql_query("set names 'utf8'");`

这下题主你明白了吧,页面设置的编码显示和对数据库中取来的数据这是两个完全不同的过程,更不用说使页面编码混乱了。
为了得到更确切的答案,你可以不做任何处理的时候直接做:

  echo mb_detect_encoding($res['test']);

你会发现输出 ASCII,也就是说默认的编码方式是 ASCII 编码,这也就是为什么我一开始说的 utf-8gbk 都兼容 ASCII 编码的原因。所以为了能正常显示中文,你必须要对其进行操作。
让我们把整个过程再分析一遍:
1.数据库取来的数据(假设为中文),它是按照 gbk 编码存储的。
2.因为你设置了 set names 'gbk',所以计算机可以知道数据的正确编码,因此得到真实的文本内容。
3.得到文本内容后,再打印到屏幕上时,此时才是按照页面显示的编码设置 utf-8 进行显示。
整个过程理清后,我相信题主应该不会再觉得页面会产生编码混乱了吧。

【热门文章】
【热门文章】