Исправление некорректной кодировки UTF-8
Я нахожусь в процессе исправления неправильной кодировки UTF-8. В настоящее время я использую PHP 5 и MySQL.
В моей базе данных есть несколько случаев плохих кодировок, которые печатаются как: î
- Сортировка базы данных: utf8_general_ci
- PHP использует правильный заголовок UTF-8
- Notepad++ настроен на использование UTF-8 без спецификации
- управление базой данных осуществляется в phpMyAdmin
- не все случаи акцентированных символов сломаны
Мне нужна какая-то функция, которая поможет мне сопоставить экземпляры ®®, ÃÂ, ü и других подобных им с их акцентированными символами UTF-8.
Ответы
Ответ 1
Мне приходилось пытаться "исправить" несколько обломанных ситуаций UTF8 в прошлом, и, к сожалению, это никогда не было легко и часто довольно невозможно.
Если вы не можете точно определить, как он был сломан, и он всегда был сломан точно так же, тогда будет трудно "отменить" урон.
Если вы хотите попытаться отменить повреждение, лучше всего начать писать примерный код, где вы производите многочисленные варианты вызовов mb_convert_encoding(), чтобы узнать, можете ли вы найти комбинацию "от" и "от", to ', который фиксирует ваши данные. В конце концов, часто лучше даже не беспокоиться о том, чтобы фиксировать старые данные из-за уровней боли, но вместо этого просто исправить ситуацию в будущем.
Однако, прежде чем делать это, вам нужно убедиться, что вы исправите все, что вызывает эту проблему, в первую очередь. Вы уже упоминали, что сортировка и редакторы таблиц базы данных установлены правильно. Но есть еще места, где вам нужно проверить, чтобы все было правильно UTF-8:
- Убедитесь, что вы обслуживаете свой HTML как UTF-8:
- header ( "Content-Type: text/html; charset = utf-8" );
- Измените свою кодировку PHP по умолчанию на utf-8:
- ini_set ( "default_charset", 'utf-8');
- Если ваша база данных не ВСЕГДА разговаривает в utf-8, вам может потребоваться рассказать об этом в каждом соединении, чтобы обеспечить ее в режиме utf-8, в MySQL вы это делаете, выпуская:
- Возможно, вам нужно будет сказать, что ваш веб-сервер всегда пытается поговорить в UTF8, в Apache эта команда:
- Наконец, вам нужно ВСЕГДА убедиться, что вы используете функции PHP, которые являются правильной жалобой UTF-8. Это означает, что всегда используйте строковые функции mb_ * в стиле "многобайтовые". Это также означает, что при вызове функций, таких как htmlspecialchars(), вы включаете соответствующий параметр "utf-8" charset в конце, чтобы убедиться, что он не кодирует их неправильно.
Если вы пропустите какой-либо один шаг через весь процесс, кодировка может быть искажена и возникают проблемы. Как только вы попадаете в "паз" для выполнения utf-8, все это становится второй натурой. И, конечно же, PHP6 должен быть полностью разовой жалобой от getgo, что сделает многое из этого проще (надеюсь)
Ответ 2
Если у вас есть двойные кодированные символы 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/
Ответ 3
Если вы 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
Скачать:
https://github.com/neitanod/forceutf8
Ответ 4
У меня была проблема с xml файлом, который имел сломанную кодировку, он сказал, что это utf-8, но у него были символы, где не utf-8.
После нескольких проб и ошибок с mb_convert_encoding()
мне удастся исправить его с помощью
mb_convert_encoding($text, 'Windows-1252', 'UTF-8')
Ответ 5
Как заметил Дэн, вам нужно преобразовать их в двоичные, а затем преобразовать/исправить кодировку.
Например, для utf8, хранящегося как latin1, следующий SQL будет исправлять его:
UPDATE table
SET field = CONVERT( CAST(field AS BINARY) USING utf8)
WHERE $broken_field_condition
Ответ 6
Я знаю, что это не очень элегантно, но после того, как было упомянуто, что строки могут быть закодированы двойным образом, я сделал эту функцию:
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;
}
Это, кажется, отлично работает, чтобы удалить двойное кодирование, которое я испытываю. Вероятно, мне не хватает некоторых персонажей, которые могут быть проблемой для других. Однако для моих нужд он отлично работает.
Ответ 7
Способ преобразования в двоичный код, а затем для исправления кодировки
Ответ 8
Еще одна вещь, которую нужно проверить, которая оказалась моим решением (найдено здесь), - это то, как данные возвращаются с вашего сервера. В моем приложении я использую 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'"));
Ответ 9
Похоже, ваш utf-8 интерпретируется как iso8859-1 или Win-1250 в какой-то момент.
Когда вы говорите: "В моей базе данных у меня есть несколько примеров неправильных кодировок" - как вы это проверили? Через ваше приложение, phpmyadmin или клиент командной строки? Все ли коды utf-8 отображаются так или только некоторые? Возможно, у вас были неправильные кодировки, и он был неправильно преобразован из iso8859-1 в utf-8, когда он уже был utf-8?
Ответ 10
У меня была такая же проблема давным-давно, и она исправила ее с помощью
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-15">
Ответ 11
Я нашел решение после нескольких дней поиска. Мой комментарий будет похоронен, но в любом случае...
-
Я получаю поврежденные данные с помощью php.
-
Я не использую имена заданий UTF8
-
Я использую utf8_decode() для своих данных
-
Я обновляю свою базу данных своими новыми декодированными данными, все еще не использую имена наборов UTF8
и voilà:)
Ответ 12
У этого script был хороший подход. Преобразование его на выбранный вами язык не должно быть слишком сложным:
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;
}
Ответ 13
@Себастьян Гриньоли запустил следующий пример:
echo Encoding::fixUTF8("Fédération Camerounaise de Football\n"); echo Encoding::fixUTF8("Fédération Camerounaise de Football\n"); echo Encoding::fixUTF8("FÃÂédÃÂération Camerounaise de Football\n"); echo Encoding::fixUTF8("Fédération Camerounaise de Football\n");
и получил следующий результат:
Fédération Camerounaise de Football Fédération Camerounaise de Football FÃÃédÃÃération Camerounaise de Football Fédération Camerounaise de Football
-edit:
Вышеуказанные результаты были, когда я писал в файл, например, так:
fclose(STDOUT);
$STDOUT = fopen('pathtofile.txt', 'a');
echo Encoding::fixUTF8("Fédération Camerounaise de Football\n");
echo Encoding::fixUTF8("Fédération Camerounaise de Football\n");
echo Encoding::fixUTF8("Fédération Camerounaise de Football\n");
echo Encoding::fixUTF8("Fédération Camerounaise de Football\n");
хотя вывод его на стандартный вывод работал нормально.
редактировать 2:
используйте print
вместо echo
при записи в файл, иначе он не будет работать