我有一个带字符串的 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
,在 UTF-8 中,即 C3 AA
。
另一个示例:西类牙语倒置问号 (¿
) 为 C8 83 E2 80 9A C3 82 C2
,它解码为 C3 3F 82 BF
,这又不是正确的 UTF-8(转换为 FF 82 BF
)。 ¿
的预期字符是 BF
,即正确 UTF-8 中的 C2 BF
。
这里发生了什么?人物是怎么乱来的?更重要的是,我该如何修复它?
(旁注 - 新服务器要求我编写 mysql_set_charset("utf8");
否则字符串也会被弄乱,尽管采用“UTF-8 as latin1”方式,而不是这种奇怪的时尚如上所示。)
长话短说:
- 通过 PHP 脚本以 UTF-8 填充 MySQL 数据库
- 休眠多年,服务器已迁移。
- 现在字符乱七八糟,见上文。
最佳答案
C3 83 C6 92 C3 82 C2 AA
This looks very much like UTF-8, so if we decode it, we get
C3 3F C2 AA
这就是将字节序列视为 UTF-8,然后将其编码为 ISO-8859-1 时得到的结果。 3F
是 ?
,它已作为替换字符包含在内,因为 UTF-8 C6 92
是 U+0192 ƒ
在 ISO-8859-1 中不存在。但它确实存在于 Windows 代码页 1252 Western European,一种与 ISO-8859-1 非常相似的编码;在那里,它是字节 0x83。
C3 83 C2 AA
再经过一轮 treat-as-UTF-8-bytes-and-encode-to-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')
).
关于php - 配置更改后,MySQL 数据库中的 UTF-8 字符串变得困惑,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7861803/