字符串编码不正确

时间:2010-12-26 21:08:22

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

注意:我已经阅读了所有通常建议的相关PHP,UTF-8字符编码文章,但我的问题与我应用这些技术之前插入的数据有关。我希望能够回顾性地解决所有字符编码问题。

现在所有连接都使用PDO设置为utf8。

PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES utf8'

不幸的是,在我实现正确的字符编码实践之前,插入了大量具有可疑编码的数据。由显示:

$sql = "SELECT name FROM data LIMIT 3";

foreach ($pdo->query($sql) as $row)
{
    $name = $row['name'];

    echo $name . "\n";
    echo utf8_encode($name) . "\n";
    echo utf8_decode($name) . "\n";
    echo htmlspecialchars($name, ENT_QUOTES, 'UTF-8') . "\n";
    echo htmlspecialchars(utf8_encode($name), ENT_QUOTES, 'UTF-8') . "\n";
    echo htmlspecialchars(utf8_decode($name), ENT_QUOTES, 'UTF-8') . "\n";
    echo '<hr/>';
}

产生:

Antonín Dvořák
AntonÃÆín DvoÃâ¦Ãâ¢ÃÆák
Anton�?­n Dvo�?�?�?¡k
Antonín Dvořák
AntonÃÆín DvoÃâ¦Ãâ¢ÃÆák

----------
Ô±Ö€Õ¡Õ´ Ô½Õ¡Õ¹Õ¡Õ¿Ö€ÕµÕ¡Õ¶
ñÃâ¬Ã¡Ã´ ýáùáÿÃâ¬ÃµÃ¡Ã¶
Ա�?ամ Խաչատ�?յան
Ô±Ö€Õ¡Õ´ Ô½Õ¡Õ¹Õ¡Õ¿Ö€ÕµÕ¡Õ¶
ñÃâ¬Ã¡Ã´ ýáùáÿÃâ¬ÃµÃ¡Ã¶

----------
Tiësto
Tiësto
Tiësto
Tiësto
Tiësto
Tiësto
----------

当使用PDO删除'SET NAMES utf8'时,它会生成数据,实际上确实有正确的项目,尽管在不同的行上:

Antonín DvoÅák
Antonín DvoÃÂák
Antonín Dvořák
Antonín DvoÅák
Antonín DvoÃÂák
Antonín Dvořák
----------
Արամ Խաչատրյան
Ô±ÖÕ¡Õ´ Ô½Õ¡Õ¹Õ¡Õ¿ÖÕµÕ¡Õ¶
???? ?????????
Արամ Խաչատրյան
Ô±ÖÕ¡Õ´ Ô½Õ¡Õ¹Õ¡Õ¿ÖÕµÕ¡Õ¶
???? ?????????
----------
Tiësto
Tiësto
Ti�sto
Tiësto
Tiësto

----------

这是有关数据库行的转储:

DROP TABLE IF EXISTS `data`;
CREATE TABLE IF NOT EXISTS `data` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `name` varchar(80) NOT NULL,
  PRIMARY KEY (`id`),
  KEY `name` (`name`(10)),
) ENGINE=InnoDB  DEFAULT CHARSET=utf8 AUTO_INCREMENT=0;

INSERT INTO `data` (`id`, `name`) VALUES (0, 'Antonín Dvořák'), (1, 'Արամ Խաչատրյան'), (2, 'Tiësto');

然后正确回显第3行“Tiësto”的第3行和第6行。我只是不确定纠正编码/检测坏字符串编码和纠正等的最佳方法是什么。

2 个答案:

答案 0 :(得分:1)

应该工作的一种方式 - 我自己没有尝试过 - 是使用phpMyAdmin将数据库转储到文件中,导入它,然后指定latin1作为编码即使它是UTF-8编码。 (您需要在导入时在下拉菜单中指定转储文件的字符集的phpMyAdmin版本)。

这会将ë变回ë。如果数据一直被破坏(即它不是有效的UTF-8字符和破坏的字符的混合),这可能有效。

显然,在尝试之前进行备份,然后用精细的梳子查看数据。

答案 1 :(得分:0)

我发现的一个相当不正统的解决方案,经过测试,似乎正在起作用:

连接A = UTF8连接 连接B =编码原始数据的旧的非UTF8连接

  • 使用A,我返回“name”,它与B正确显示但由于非UTF8 DB编码而被A损坏
  • 通过查找损坏的A值
  • 在B中查找商品ID
  • 然后使用具有正确编码的UTF8值的更新数据库

相当复杂但似乎有效。如有任何问题,请更新。