Je suis en train de réparer un mauvais encodage UTF-8. J'utilise actuellement PHP 5 et MySQL.
Dans ma base de données, j'ai quelques exemples de mauvais encodages qui s'impriment comme: î
J'ai besoin d'une sorte de fonction qui m'aidera à mapper les instances de î, ÃÂ, ü et d'autres similaires à leurs caractères UTF-8 accentués appropriés.
J'ai dû essayer de `` réparer '' un certain nombre de situations cassées UTF8 dans le passé, et malheureusement ce n'est jamais facile, et souvent plutôt impossible.
À moins que vous ne puissiez déterminer exactement comment il a été brisé, et il l'a toujours été de la même manière, il sera difficile de "réparer" les dommages.
Si vous voulez essayer de réparer les dégâts, votre meilleur pari serait de commencer à écrire un exemple de code, où vous tentez de nombreuses variantes d'appels à mb_convert_encoding () pour voir si vous pouvez trouver une combinaison de 'de' et 'à' cela corrige vos données. En fin de compte, il est souvent préférable de ne pas même se soucier de réparer les anciennes données en raison des niveaux de douleur impliqués, mais plutôt de simplement réparer les choses à l'avenir.
Cependant, avant de faire cela, vous devez vous assurer que vous corrigez tout ce qui est à l'origine de ce problème. Vous avez déjà mentionné que le classement et les éditeurs de votre table DB sont correctement définis. Mais il y a plus d'endroits où vous devez vérifier pour vous assurer que tout est correctement UTF-8:
Si vous manquez une étape de votre processus, l'encodage peut être modifié et des problèmes surviennent. Une fois que vous êtes dans le "groove" de la pratique de l'utf-8, tout cela devient une seconde nature. Et bien sûr, PHP6 est censé être une plainte entièrement unicode du getgo, ce qui facilitera beaucoup cela (espérons-le)
Si vous avez des caractères UTF8 double-encodés (diverses guillemets intelligents, tirets, apostrophe ", guillemet", etc.), dans mysql vous pouvez vider les données, puis les relire pour corriger l'encodage cassé.
Comme ça:
mysqldump -h DB_Host -u DB_USER -p DB_PASSWORD --opt --quote-names \
--skip-set-charset --default-character-set=latin1 DB_NAME > DB_NAME-dump.sql
mysql -h DB_Host -u DB_USER -p DB_PASSWORD \
--default-character-set=utf8 DB_NAME < DB_NAME-dump.sql
Il s'agissait d'un correctif à 100% pour mon UTF-8 à double codage.
Source: http://blog.hno3.org/2010/04/22/fixing-double-encoded-utf-8-data-in-mysql/
Si vous utf8_encode()
sur une chaîne qui est déjà UTF-8, alors elle semble tronquée lorsqu'elle est encodée plusieurs fois.
J'ai créé une fonction toUTF8()
qui convertit les chaînes en UTF-8.
Vous n'avez pas besoin de spécifier le codage de vos chaînes. Il peut s'agir de Latin1 (iso 8859-1), Windows-1252 ou UTF8, ou un mélange des trois.
Je l'ai utilisé moi-même sur un flux avec des encodages mixtes dans la même chaîne.
Usage:
$utf8_string = Encoding::toUTF8($mixed_string);
$latin1_string = Encoding::toLatin1($mixed_string);
Mon autre fonction fixUTF8()
corrige les chaînes UTF8 tronquées si elles étaient encodées en UTF8 plusieurs fois.
Usage:
$utf8_string = Encoding::fixUTF8($garbled_utf8_string);
Exemples:
echo Encoding::fixUTF8("Fédération Camerounaise de Football");
echo Encoding::fixUTF8("Fédération Camerounaise de Football");
echo Encoding::fixUTF8("FÃÂédÃÂération Camerounaise de Football");
echo Encoding::fixUTF8("Fédération Camerounaise de Football");
affichera:
Fédération Camerounaise de Football
Fédération Camerounaise de Football
Fédération Camerounaise de Football
Fédération Camerounaise de Football
Télécharger:
J'ai eu un problème avec un fichier xml qui avait un encodage cassé, il a dit que c'était utf-8 mais il y avait des caractères qui n'étaient pas utf-8.
Après plusieurs essais et erreurs avec la mb_convert_encoding()
j'arrive à le réparer avec
mb_convert_encoding($text, 'Windows-1252', 'UTF-8')
Comme Dan l'a souligné: vous devez les convertir en binaire, puis convertir/corriger l'encodage.
Par exemple, pour utf8 stocké en latin1, le SQL suivant le corrigera:
UPDATE table
SET field = CONVERT( CAST(field AS BINARY) USING utf8)
WHERE $broken_field_condition
Je sais que ce n'est pas très élégant, mais après avoir mentionné que les chaînes peuvent être codées en double, j'ai fait cette fonction:
function fix_double encoding($string)
{
$utf8_chars = explode(' ', 'À Á Â Ã Ä Å Æ Ç È É Ê Ë Ì Í Î Ï Ð Ñ Ò Ó Ô Õ Ö × Ø Ù Ú Û Ü Ý Þ ß à á â ã ä å æ ç è é ê ë ì í î ï ð ñ ò ó ô õ ö');
$utf8_double_encoded = array();
foreach($utf8_chars as $utf8_char)
{
$utf8_double_encoded[] = utf8_encode(utf8_encode($utf8_char));
}
$string = str_replace($utf8_double_encoded, $utf8_chars, $string);
return $string;
}
Cela semble fonctionner parfaitement pour supprimer le double encodage que je rencontre. Il me manque probablement certains des personnages qui pourraient être un problème pour d'autres. Cependant, pour mes besoins, cela fonctionne parfaitement.
Le moyen est de convertir en binaire puis de corriger l'encodage
Une autre chose à vérifier, qui s'est avérée être ma solution (trouvée ici ), est de savoir comment les données sont renvoyées depuis votre serveur. Dans mon application, j'utilise PDO pour me connecter de PHP à MySQL. J'avais besoin d'ajouter un indicateur à la connexion qui disait récupérer les données au format UTF-8
La réponse a été
$dbHandle = new PDO("mysql:Host=$dbHost;dbname=$dbName;charset=utf8", $dbUser, $dbPass,
array(PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES 'utf8'"));
j'ai eu le même problème il y a longtemps, et il l'a résolu en utilisant
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-15">
Il semble que votre utf-8 soit interprété comme iso8859-1 ou Win-1250 à un moment donné.
Lorsque vous dites "Dans ma base de données, j'ai quelques exemples de mauvais encodages" - comment avez-vous vérifié cela? Via votre application, phpmyadmin ou le client en ligne de commande? tous les encodages utf-8 apparaissent-ils comme ceci ou seulement certains? Est-il possible que les encodages soient incorrects et qu'il ait été incorrectement converti de iso8859-1 en utf-8 alors qu'il était déjà utf-8?
J'ai trouvé une solution après des jours de recherche. Mon commentaire va être enterré mais de toute façon ...
J'obtiens les données corrompues avec php.
Je n'utilise pas de noms de set UTF8
J'utilise utf8_decode () sur mes données
Je mets à jour ma base de données avec mes nouvelles données décodées, toujours pas en utilisant les noms de set UTF8
et voilà :)
Ce script avait une belle approche. Le convertir dans la langue de votre choix ne devrait pas être trop difficile:
http://plasmasturm.org/log/416/
#!/usr/bin/Perl
use strict;
use warnings;
use Encode qw( decode FB_QUIET );
binmode STDIN, ':bytes';
binmode STDOUT, ':encoding(UTF-8)';
my $out;
while ( <> ) {
$out = '';
while ( length ) {
# consume input string up to the first UTF-8 decode error
$out .= decode( "utf-8", $_, FB_QUIET );
# consume one character; all octets are valid Latin-1
$out .= decode( "iso-8859-1", substr( $_, 0, 1 ), FB_QUIET ) if length;
}
print $out;
}