Исправление сломанной кодировки UTF8
Я нахожусь в процессе исправления некоторых плохих кодировок UTF8. В настоящее время я использую PHP 5 и MySQL
в моей базе данных у меня есть несколько экземпляров плохих кодировок, которые печатают как: î
- параметры сортировки базы данных utf8_general_ci
- PHP использует правильный заголовок UTF8
- Notepad++ настроен на использование UTF8 без BOM
- управление базами данных осуществляется в phpMyAdmin
- не все случаи акцентированных символов являются сломанный
Что мне нужно, так это какая-то функция, которая поможет мне сопоставить экземпляры î, ÃÂ, Ã⠼ и другие, подобные им, с их правильными акцентированными символами UTF8.
12 ответов:
Я должен был попытаться "исправить" ряд utf8 сломанных ситуаций в прошлом, и, к сожалению, это никогда не бывает легко, и часто довольно невозможно.
Если вы не можете точно определить, как он был сломан, и он всегда был сломан точно таким же образом, тогда будет трудно "отменить" повреждение.
Если вы хотите попытаться устранить повреждение, лучше всего начать писать пример кода, в котором вы пытаетесь использовать многочисленные варианты вызовов mb_convert_encoding (), чтобы увидеть, если вы можете найти комбинацию 'от' и 'до', который фиксирует ваши данные. В конце концов, часто лучше даже не беспокоиться о фиксации старых данных из-за уровня боли, но вместо этого просто исправить ситуацию в будущем.
однако, прежде чем делать это, вы должны убедиться, что вы исправить все, что вызывает эту проблему в первую очередь. Вы уже упоминали, что параметры сортировки и редакторы таблиц БД установлены правильно. Но есть еще места, где вам нужно проверить, чтобы убедиться, что все правильно UTF-8:
- убедитесь, что вы обслуживаете свой HTML как UTF-8:
- заголовок ("Content-Type: text / html; charset=utf-8");
- измените кодировку PHP по умолчанию на utf-8:
- ini_set ("default_charset", 'utf-8');
- если ваша база данных не всегда говорит в utf-8, то вам может потребоваться рассказать об этом на каждом основание соединения, чтобы гарантировать, что оно находится в режиме utf-8, в MySQL вы делаете это, выпуская:
- charset utf8
- возможно, вам придется сказать вашему веб-серверу всегда пытаться говорить в UTF8, в Apache эта команда:
- AddDefaultCharset UTF-8
- наконец, вы всегда должны убедиться, что вы используете PHP функции, которые правильно UTF-8 жалоба. Это означает всегда использовать mb_* стиле 'многобайтовых известно' строковые функции. Это также означает, что при вызове таких функций, как htmlspecialchars (), вы включаете соответствующий параметр кодировки "utf-8" в конце, чтобы убедиться, что он не кодирует их неправильно.
Если вы пропустите какой-либо один шаг через весь процесс, кодировка может быть искажена и возникают проблемы. Как только вы попадаете в " паз " выполнения utf-8, все это становится второй натурой. И, конечно же, PHP6 должен быть полностью unicode жалоба от getgo, который сделает много этого проще (надеюсь)
Если у вас есть дважды закодированные символы UTF8 (различные умные кавычки, тире, Апостроф, кавычки и т. д.), В mysql вы можете сбросить данные, а затем прочитать их обратно, чтобы исправить сломанную кодировку.
такой:
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Это было 100% исправление для моего двойного кодирования UTF-8.
источник: http://blog.hno3.org/2010/04/22/fixing-double-encoded-utf-8-data-in-mysql/
если вы
utf8_encode()в строке, которая уже является UTF-8, тогда она выглядит искаженной, когда она кодируется несколько раз.Я сделал функцию
toUTF8()который преобразует строки в UTF-8.вам не нужно указать кодировку строк. Это может быть Latin1 (iso 8859-1), Windows-1252 или UTF8, или смесь этих трех.
Я сам использовал это на ленте со смешанными кодировками в той же строке.
использование:
$utf8_string = Encoding::toUTF8($mixed_string); $latin1_string = Encoding::toLatin1($mixed_string);мой другая функция
fixUTF8()исправляет искаженные строки UTF8, если они были закодированы в UTF8 несколько раз.использование:
$utf8_string = Encoding::fixUTF8($garbled_utf8_string);примеры:
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");вывод:
Fédération Camerounaise de Football Fédération Camerounaise de Football Fédération Camerounaise de Football Fédération Camerounaise de Footballскачать:
Как отметил Дэн: вам нужно преобразовать их в двоичный код, а затем преобразовать/исправить кодировку.
например, для utf8, хранящегося как latin1, следующий SQL исправит его:
UPDATE table SET field = CONVERT( CAST(field AS BINARY) USING utf8) WHERE $broken_field_condition
у меня была проблема с xml-файлом, который имел сломанную кодировку, он сказал, что это utf-8, но у него были символы, которые не были utf-8.
После нескольких проб и ошибок сmb_convert_encoding()мне удается исправить это с помощьюmb_convert_encoding($text, 'Windows-1252', 'UTF-8')
Я знаю, что это не очень элегантно, но после того, как было упомянуто, что строки могут быть дважды закодированы, я сделал эту функцию:
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; }это, кажется, работает отлично, чтобы удалить двойную кодировку, которую я испытываю. Я, вероятно, не хватает некоторых персонажей, которые могут быть проблемой для других. Однако для моих нужд он работает отлично.
еще одна вещь для проверки, которая оказалась моим решением (найдено здесь), как данные возвращаются с сервера. В моем приложении я использую PDO для подключения от PHP к MySQL. Мне нужно было добавить флаг к соединению, в котором говорилось, что данные возвращаются в формате UTF-8
ответ
$dbHandle = new PDO("mysql:host=$dbHost;dbname=$dbName;charset=utf8", $dbUser, $dbPass, array(PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES 'utf8'"));
похоже, что ваш utf-8 в какой-то момент интерпретируется как iso8859-1 или Win-1250.
когда вы говорите "в моей базе данных у меня есть несколько экземпляров плохих кодировок" - как вы это проверили? Через ваше приложение, phpmyadmin или клиент командной строки? Являются все кодировки utf-8 появляются так или только некоторые? Возможно ли, что у вас были неправильные кодировки, и он был неправильно преобразован из iso8859-1 в utf-8, когда он уже был utf-8?
У меня была такая же проблема давно, и он починил его с помощью
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-15">
Я нашел решение после долгих дней поиска. Мой комментарий будет похоронен, но в любом случае...
Я получаю поврежденные данные с php.
Я не использую имена наборов UTF8
Я использую utf8_decode () на моих данных
Я обновляю свою базу данных с моими новыми декодированными данными, все еще не используя имена наборов UTF8
и вуаля :)
этот скрипт имел хороший подход. Преобразования в языке не должно быть слишком сложно:
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; }
Comments