Подтвердить что ты не робот

Исправление некорректной кодировки UTF-8

Я нахожусь в процессе исправления неправильной кодировки UTF-8. В настоящее время я использую PHP 5 и MySQL.

В моей базе данных есть несколько случаев плохих кодировок, которые печатаются как: î

  • Сортировка базы данных: utf8_general_ci
  • PHP использует правильный заголовок UTF-8
  • Notepad++ настроен на использование UTF-8 без спецификации
  • управление базой данных осуществляется в phpMyAdmin
  • не все случаи акцентированных символов сломаны

Мне нужна какая-то функция, которая поможет мне сопоставить экземпляры ®®, ÃÂ, ü и других подобных им с их акцентированными символами UTF-8.

4b9b3361

Ответ 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 вы это делаете, выпуская:
    • charset utf8
  • Возможно, вам нужно будет сказать, что ваш веб-сервер всегда пытается поговорить в UTF8, в Apache эта команда:
    • AddDefaultCharset UTF-8
  • Наконец, вам нужно ВСЕГДА убедиться, что вы используете функции 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 при записи в файл, иначе он не будет работать