2010-12-26 6 views
1

Note: J'ai lu tous les articles de codage de caractères PHP, UTF-8, qui sont généralement suggérés, mais ma question concerne les données insérées avant que j'applique de telles techniques. Je souhaite corriger rétrospectivement tous les problèmes d'encodage de caractères.Codages de chaîne incorrects

Maintenant toutes les connexions sont définies comme utf8 en utilisant PDO.

PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES utf8' 

Malheureusement, une grande quantité de données a été inséré qui est de l'encodage douteux avant d'avoir mis en œuvre des pratiques de codage de caractères correct. Comme le montre par:

$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/>'; 
} 

qui produit:

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 
---------- 

Lors de la suppression « SET NAMES utf8 » avec AOP elle produit les données, qui n'ont en fait les éléments corrects, bien que sur les différentes lignes:

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 

---------- 

Et voici une décharge des lignes de base de données concernée:

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'); 

Les 3ème et 6ème lignes de la 3ème rangée "Tiësto" sont alors correctement répercutées. Je ne suis pas sûr quelle est la meilleure façon de corriger les encodages/détecter les encodages de mauvaises chaînes et corriger, etc

+0

Ceci a été demandé mais IMO pas complètement répondu ici: http://stackoverflow.com/questions/1344692/i-need-help-fixing-broken-utf8-encoding (Ne pas voter comme doublon parce que ce * est * réparable) –

+0

Dans un premier temps, pour confirmer: Êtes-vous sûr à 100% que vos données de base de données sont brisées? Qu'avez-vous utilisé pour faire la décharge?Un programme client tel que phpMyAdmin ou HeidiSQL affiche-t-il les caractères brisés lorsque vous parcourez la table? –

+0

phpMyAdmin affiche ce qui est affiché sur la ligne supérieure. – James

Répondre

1

Une façon que devrait travail - je n'ai pas essayé moi-même - est de vider la base de données dans un fichier utilisant phpMyAdmin, en l'important, et en spécifiant latin1 comme codage même s'il s'agit d'un codage UTF-8. (Vous avez besoin de la version de phpMyAdmin qui spécifie le jeu de caractères du fichier de vidage dans un menu déroulant lors de l'importation).

Ceci devrait retourner ë en ë. Si les données sont systématiquement rompues (c'est-à-dire que ce n'est pas un mélange de caractères UTF-8 valides et de caractères cassés), cela peut fonctionner.

De toute évidence, faites des sauvegardes avant d'essayer ceci, et regardez ensuite les données avec un peigne fin.

0

Une solution assez peu orthodoxe que j'ai trouvé et après le test, semble fonctionner est:

Connexion A = Connexion UTF8 Connexion B = ancienne connexion non-UTF8, données codées d'origine

  • Avec A, je retourne "nom" qui s'affiche correctement avec B, mais est corrompu avec A en raison de codage non-UTF8 DB
  • Trouver l'ID d'élément dans B en recherchant corrompu A valeur
  • Puis en utilisant une mise à jour DB avec c Valeur UTF8 codée de manière arbitraire

Plutôt compliqué mais il semble fonctionner. Mettra à jour si des problèmes.