Исправление сломанной кодировки UTF8



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



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




  • параметры сортировки базы данных utf8_general_ci

  • PHP использует правильный заголовок UTF8

  • Notepad++ настроен на использование UTF8 без BOM

  • управление базами данных осуществляется в phpMyAdmin

  • не все случаи акцентированных символов являются сломанный


Что мне нужно, так это какая-то функция, которая поможет мне сопоставить экземпляры î, ÃÂ, Ã⠼ и другие, подобные им, с их правильными акцентированными символами UTF8.

912   12  

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

скачать:

https://github.com/neitanod/forceutf8

Как отметил Дэн: вам нужно преобразовать их в двоичный код, а затем преобразовать/исправить кодировку.

например, для 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">

Я нашел решение после долгих дней поиска. Мой комментарий будет похоронен, но в любом случае...

  1. Я получаю поврежденные данные с php.

  2. Я не использую имена наборов UTF8

  3. Я использую utf8_decode () на моих данных

  4. Я обновляю свою базу данных с моими новыми декодированными данными, все еще не используя имена наборов 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

    Ничего не найдено.