【问题标题】:List of 'messed up characters' in utf8utf8 中的“混乱字符”列表
【发布时间】:2011-08-23 23:21:32
【问题描述】:

我的一个客户有一个网站,该网站被托管公司强制在完整数据库上设置字符集完全搞砸了。我们之前在角色设置方面遇到过麻烦,但现在它只是一部直截了当的戏剧!

到目前为止,我已将 charset=utf-8 添加到页面内容类型,并将 mysql 连接的字符集设置为 utf8。现在是时候替换所有字符了。到目前为止,我发现的是:

ö = ö
ë = ë
é = é

数据库中的数据正在更新,如下所示:

UPDATE table SET `fieldname` = REPLACE(`fieldname`, 'ö', 'ö');

现在我只需要找到所有乱码的完整列表。我尝试使用 MySQL 查询搜索 field LIKE '%Ã%',但这会返回数据库中的所有记录。

Google 也只在其他人遇到问题的一些主题中显示几个字符(主要是上面的 3 个),但似乎没有我能找到的这些字符的完整列表(或至少是最常见的)用于查找和替换我的客户的所有数据。

如果有人可能知道这样的位置或能够完成我的列表,作为回报,我将创建一个包含这些字符的页面来帮助其他人(除非已经有一个列表,我当然不知道某个地方)。

//EDIT:

它适用于最常见的欧洲字符,例如 é è ë、á à ä、ö ó ò、ï、ü 以及 ringel-S(德语双 S)。对于像 ñ 或 ã 这样的跨越符号而言,不是那么多,但如果它们在某个列表中,那将不胜感激。

//EDIT 2:

我使用本文第一部分中的 2 个 ALTER 查询更新了 MySQL 数据库和表:http://developer.loftdigital.com/blog/php-utf-8-cheatsheet。到目前为止,我没有使用 mb_ 函数,也没有像看起来那样做任何 MB 配置。

文件中的标头都设置为 utf-8(我仍然需要检查一些 ajax 脚本的标头,但不确定是否需要这样做,但这样做不会有害)。并且文件都保存为没有BOM的UTF8。 PHPFreakMailer 也通过将字符集设置为 utf-8 来更新。

Bad enough,我仍然有这些奇怪的字符。我不认为他们会自己离开,但至少值得这样希望:-) 那么我应该采取的最后一步是什么?继续使用 REPLACE 查询并手动更改所有奇怪的字符?

提前致谢!

【问题讨论】:

  • 为什么不强制表格和连接到您需要的字符集?并不是说这样做实际上会解决真正的问题......

标签: php utf-8 character-encoding special-characters


【解决方案1】:

这有点疯狂;你认为“ö”在什么字符集中?

看起来这实际上是一个正确的 UTF-8 序列(因为它是两个字节),您只是将其显示为 ISO-8559-1。

编辑

根据您的评论,我认为正在发生以下情况:

认为(但实际上不是 100% 肯定)正确的 UTF-8 二进制序列存储在数据库中。但由于该表标记为 ISO-8559-1,并且您要求自动转换字符集。所以它认为它是 ISO-8559-1(看起来像 ö),但随后尝试将其转换为 UTF-8。

如果 strlen('ö') 是 4 而不是 2,您应该能够验证这一点。如果长度确实是 2,那么您的浏览器编码不知何故搞砸了。

要解决此问题,请不要将 MySQL 设置为对字符进行编码。

选项 2

数据也可以在表中进行“双重编码”。要检查这一点,只需检查数据库上的字符串长度。如果 'ö' 是 4 个字节长,这就是问题所在。

在这种情况下,我的建议是不要尝试制作大的“混乱角色”地图。您应该能够简单地对字符串进行“utf8_decode”。通常这个函数会输出一个 ISO-8559-1 字符串,但在你的情况下.. 它应该是原始有效的 UTF-8 字符串。

我希望这行得通!

编辑2

好吧,我相信发生的事情是选项 2。用简单的 (php) 术语来说:

$output = utf8_encode(utf8_encode('string'));

所以一个 utf8_decode() 就足够了。

不过,在运行迁移脚本之前请先测试一下 :)

【讨论】:

  • 我已根据http://developer.loftdigital.com/blog/php-utf-8-cheatsheet 将DB 字符集设置为utf8,我应该采取哪些其他步骤?我注意到仍然有一些旧字符显示为 ë 我猜这是因为这些数据是使用 ISO 标头保存的。我在帖子中提到的替换查询是将它们全部转换回来的正确方法吗?
  • 检查我原来的建议。首先找出那些“奇怪”字符有多长。如果它们确实是您预期的两倍(4 而不是 2),那么您的字符将被双重编码。
  • 好的,它说 strlen() = 4,替换数据库中的所有字符也是一个有效的选项吗?由于我想在未来正常运行,所以保存数据应该是我最好的解决方案。
  • 太好了,所以我现在实际上在想“选项 2”是最有可能的情况。要返回原始数据,只需将“UTF-8”转换为“ISO-8559-1”即可。输出无论如何都是UTF-8。
  • 我该怎么做呢? REPLACE 查询基本上不是以另一种方式做同样的事情吗? (用单编码替换双编码数据?)
【解决方案2】:

如果他们强制更改字符,为什么您的数据库没有转换?您的表格是否仍然是旧字符集(请参阅您的 phpMyAdmin 表格信息)。

如果数据显示在您的 phpMyAdmin 中或仅显示在您的网页上,数据是否错误? -> 你的名字和排序规则应该改变,以及标题和文件类型(安全文件为 utf-8)。

或者试试:

ALTER TABLE tbl_name CONVERT TO CHARACTER SET utf8 COLLATE utf8_general_ci;

只有在 MySQL 中没有任何选项时,我才会开始替换字符。

【讨论】:

  • 好吧好吧,在 PHPMyAdmin 和网页上的字符都显示为“ö”,所以它们都显示了奇怪的字符。该网页具有 utf8 标头、字符集和 utf8 mysql 连接。数据库在“latin1”上有“character_set_database”。我最大的担心是更改数据库中的charset会导致所有数据再次混乱,还是没有机会发生这种情况?
  • 我更新了数据库的字符集和排序规则,但是这些字符仍然显示不好,因为它们可能已保存/转换为 ISO 显示的字符(我不知道还会发生什么......)所以我猜想我还是应该用我的方法来转换所有奇数字符。
  • 感谢您的帮助。为您的时间和思考 +1。
【解决方案3】:

既然您已经用“php”标记了这个问题,我假设您使用 PHP 阅读了数据库及其值?如果是这样,如果您不再控制数据库,请查看mb_convert_encoding

更好的解决方案是修复数据和表格字符集之间的不一致。备份数据库(以防万一),并将所有表 列更改为 UTF-8。 注意:在使用 MySQL 时,仅更改表的字符集不够,您必须按列执行此操作。

【讨论】:

  • 感谢您的警告,我注意到列仍然有 latin1 排序规则,我想仍然是 utf8 字符集。这是我需要的正确查询吗? ALTER TABLE table MODIFY column CHARACTER SET utf8 COLLATE utf8_general_ci;?我最好自己编写一个脚本,然后为每一列执行此操作。
  • 是的。该脚本可能也在互联网上漫游,因此您不必编写它。
  • 我想在运行它之前进行备份也不会太糟糕。
  • 好的,我在 serverfault.com 上找到了这篇文章:http://serverfault.com/questions/65043/alter-charset-and-collation-in-all-columns-in-all-tables-in-mysql。有一个查询:SELECT distinct CONCAT( 'alter table ', TABLE_SCHEMA, '.', TABLE_NAME, ' CONVERT TO CHARACTER SET utf8 COLLATE utf8_general_ci;' ) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = 'DBname'; 似乎在做我需要的事情?
  • 这应该让你得到查询。确实,请务必先进行备份!另外,如果有机会,不要在实时数据库上执行此操作,请先在测试数据库上执行此操作!
【解决方案4】:

你为什么不使用:ä = äö = ö,...

在 php 中执行htmlentities();,它会将所有特殊字符转换为实体。
我认为这将是最简单的方法。

【讨论】:

  • 这将是太多的工作,因为很多数据已经被托管服务提供商不断变化的数据集削弱了。如果完成,我必须修复当前字符我不相信使用 htmlentities() 是必要的,因为所有字符集都是相同的(因此将它们保存到数据库并从数据库中读取它们应该不是问题)。谢谢你的想法!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-07-26
  • 2011-03-14
  • 2011-04-22
  • 1970-01-01
  • 1970-01-01
  • 2012-08-20
  • 1970-01-01
相关资源
最近更新 更多