配置更改后,MySQL数据库中的UTF-8字符串搞乱了

时间:2011-10-22 18:42:39

标签: php mysql utf-8

我有一个带有字符串的MySQL,我暂时休眠了一段时间。现在我再次拾起它,我注意到所有特殊字符都搞砸了。我的ISP已将服务器移植到另一台机器上,我怀疑这可能发生在它发生的时候。

数据库由PHP脚本填充。一切都应该是UTF-8,这就是数据库的设置。

但是,这就是字符串现在的样子:

fête

这四个特殊字符应该是一个字符ê,字符串应该是fête

现在看来这只是重新编码两次,但这似乎不对。十六进制中的这四个字符是:

C3 83 C6 92 C3 82 C2 AA

这看起来非常像UTF-8,所以如果我们解码它,我们就会得到

C3 3F C2 AA

这不是UTF-8(因为3F),但让我们再次解码:

FF AA

这不是UTF-8。

ê字符EA,格式为C3 AA,格式为¿

另一个例子:西班牙语颠倒的问号(C8 83 E2 80 9A C3 82 C2)与C3 3F 82 BF一样,解码为FF 82 BF,这不再是正确的UTF-8(转换为¿)。 BF的预期字符为C2 BF,即正确的UTF-8中的mysql_set_charset("utf8");

这里发生了什么?角色怎么搞砸了?更重要的是,我该如何解决?

(旁注 - 新服务器要求我写{{1}}或者字符串也搞乱了,虽然在“UTF-8 as latin1”的方式中,不是如上所示的这种奇怪的方式。)< / p>

TL; DR:

  • MySQL数据库通过PHP脚本
  • 以UTF-8填充
  • 休眠多年,服务器已迁移。
  • 现在人物搞砸了,见上文。

2 个答案:

答案 0 :(得分:8)

C3 83 C6 92 C3 82 C2 AA
  

这看起来非常像UTF-8,所以如果我们解码它,我们就会得到

C3 3F C2 AA

如果将字节序列视为UTF-8,则将其编码为ISO-8859-1。 3F?,已作为替换字符包含在内,因为UTF-8 C6 92是U + 0192 ƒ,在ISO-8859-1中不存在。但它确实存在于Windows代码页1252西欧,编码非常类似于ISO-8859-1;那里,它是字节0x83。

C3 83 C2 AA

通过另一轮对待UTF-8字节和编码到cp1252,你得到:

C3 AA

最后是ê的UTF-8。

请注意,即使您明确地将非XML HTML页面作为ISO-8859-1提供服务,由于历史原因令人讨厌,浏览器实际上也会使用cp1252编码。

不幸的是,MySQL没有cp1252编码; latin1是(正确)ISO-8859-1。因此,您将无法通过转储为latin1然后重新加载为utf8(两次)来修复数据。您必须使用文本编辑器处理脚本,该文本编辑器可以另存为(或者例如在Python file(path, 'rb').read().decode('utf-8').encode('cp1252').decode('utf-8').encode('cp1252')中)。

答案 1 :(得分:1)

我怀疑你可能会将你的角色存储为latin1(或类似)数据库中的UTF8字符串。这就是为什么你有双重编码&#39;问题。使数据库的CHARSET UTF8应该修复它。也可能需要转储/导入数据,这些都是这样的:

$ mysqldump --default-character-set=latin1  --skip-set-charset --databases xxx > xxx.sql
$ mysql --default-character-set=utf8 < xxx.sql

但这只是一个建议,可能会有效,但在你的具体情况下不必这样做。