как определить и исправить кодировку символов в базе данных mysql через php?

Я получил эту базу данных, полную имен людей и данных на французском языке, что означает использование таких символов, как é, è, ö, û и т. Д. Около 3000 записей.

Судя по всему, данные внутри кодировались иногда с использованием utf8_encode (), а иногда - нет. Это приводит к неправильному выводу: в некоторых местах символы отображаются нормально, в других - нет.

Сначала я попытался отследить каждое место в пользовательском интерфейсе, где возникают эти проблемы, и использовать utf8_decode () там, где это необходимо, но это действительно не практичное решение.

Я провел некоторое тестирование, и нет причин использовать utf8_encode в первую очередь, поэтому я бы предпочел все это удалить и просто работать в UTF8 везде - на уровне браузера, промежуточного программного обеспечения и базы данных. Поэтому мне нужно очистить базу данных, преобразовав все неправильно закодированные данные в ее очищенную версию.

Вопрос: можно ли создать в php функцию, которая проверяла бы, правильно ли закодирована строка utf8 (без utf8_encode) или нет (с utf8_encode), и, если да, преобразовывала бы ее обратно в исходное состояние?

Другими словами: я хотел бы знать, как я могу обнаружить содержимое utf8, которое было от utf8_encode () до содержимого utf8, которое не было utf8_encode () d.

** ОБНОВЛЕНИЕ: ПРИМЕР **

Вот хороший пример: вы берете строку, полную специальных символов, и берете копию этой строки и ее utf8_encode (). Функция, о которой я мечтаю, берет обе строки, оставляет первую нетронутой, а вторая строка теперь такая же, как и первая строка.

Я пробовал это:

$loc_fr = setlocale(LC_ALL, 'fr_BE.UTF8','fr_BE@euro', 'fr_BE', 'fr', 'fra', 'fr_FR');
$str1= "éèöûêïà ";
$str2 = utf8_encode($str1);

function convert_charset($str) {
    $charset=  mb_detect_encoding($str);
    if( $charset=="UTF-8" ) {
        return utf8_decode($str);
    }
    else {
        return $str;
    }
}
function correctString($str) {
    echo "\nbefore: $str";
    $str= convert_charset($str);
    echo "\nafter: $str"; 
}

correctString($str1);
echo('<hr/>'."\n");
correctString($str2);

И это дает мне:

before: éèöûêïà after: ������� 
before: éèöûêïà  after: éèöûêïà 

Спасибо,

Алекс


person pixeline    schedule 01.10.2009    source источник


Ответы (5)


Из вопроса не совсем понятно, какую линзу кодировки символов вы просматриваете в данный момент (это зависит от значений по умолчанию вашего текстового редактора, заголовков браузера, конфигурации базы данных и т. Д.), А также от того, какие преобразования кодировки символов претерпели данные. Может случиться так, что, например, путем настройки конфигурации базы данных все будет исправлено, и это намного лучше, чем внесение частичных изменений в данные.

Похоже, это может быть проблема двойного кодирования utf8, и в этом случае как исходные, так и поврежденные данные будут в utf8, поэтому обнаружение кодировки не даст вам нужной информации. Подход в этом случае требует делать предположения о том, какие символы могут разумно появляться в ваших данных: что касается PHP и Mysql, «Ã ©» является совершенно законным utf8, поэтому вы должны сделать суждение на основе того, что вы знаете о данные и их авторы, что они должны быть повреждены. Это рискованные предположения, если вы просто технический специалист. К счастью, если вы знаете, что данные на французском языке и есть только 3000 записей, вероятно, можно делать такие предположения.

Ниже приведен сценарий, который вы можете адаптировать, прежде всего, для проверки ваших данных, затем для их исправления и, наконец, для повторной проверки. Все, что он делает, - это обрабатывает строку как utf8, разбивает ее на символы и сравнивает символы с белым списком ожидаемых французских символов. Это сигнализирует о проблеме, если строка либо не в utf8, либо содержит символы, которые обычно не ожидаются во французском языке, например:

PROBABLY OK     Côte d'Azur
HAS NON-WHITELISTED CHAR        Côte d'Azur    195,180 ô
NON-UTF8        C�e d'Azur

Вот сценарий, вам необходимо загрузить зависимые функции Unicode с http://hsivonen.iki.fi/php-utf8/

<?php

// Download from http://hsivonen.iki.fi/php-utf8/
require "php-utf8/utf8.inc";

$my_french_whitelist = array_merge(
  range(0,127), // throw in all the lower ASCII chars
  array(
    0xE8, // small e-grave
    0xE9, // small e-acute
    0xF4, // small o-circumflex
    //... Will need to add other accented chars,
    // Euro sign, and whatever other chars
    // are normally expected in the data.
  )
);

// NB, whether this string literal is in utf8
// depends on the encoding of the text editor
// used to write the code
$str1 = "Côte d'Azur";
$test_data = array(
  $str1,
  utf8_encode($str1),
  utf8_decode($str1),
);

foreach($test_data as $str){
  $questionable_chars = non_whitelisted(
    $my_french_whitelist,
    $str
  );
  if($questionable_chars===true){
    p("NON-UTF8", $str);
  }else if ($questionable_chars){
    p(
      "HAS NON-WHITELISTED CHAR",
      $str,
      implode(",", $questionable_chars),
      unicodeToUtf8($questionable_chars)
    );
  }else{
    p("PROBABLY OK", $str);
  }
}

function non_whitelisted($whitelist, $utf8_str){
  $codepoints = utf8ToUnicode($utf8_str);
  if($codepoints===false){ // has non-utf8 char
    return true;
  }
  return array_diff(
    array_unique($codepoints),
    $whitelist
  );
}


function p(){
  $args = func_get_args();
  echo implode("\t", $args), "\n";
}
person Community    schedule 02.10.2009
comment
Я думаю, вы точно поняли суть проблемы, и я очень ценю ваш обширный вклад. Я попробую ваш сценарий и вернусь к вам. Вопрос: где я могу найти код других символов с диакритическими знаками для добавления в белый список? Как это называется? Это столбец шестнадцатеричного кода на этой странице: webdesign.about.com/ od / localization / l / blhtmlcodes-fr.htm? - person pixeline; 02.10.2009
comment
Этот список должен охватывать большую часть того, что вам нужно, и если вам нужны другие символы, он основан на коде Unicode, который вы можете найти где-нибудь вроде fileformat.info/info/unicode/index.htm. Знак евро может вызвать некоторые проблемы - его кодовая точка Unicode - U + 20AC, но в HTML возникло соглашение об использовании символьной ссылки 80, что и используется в списке webdesign.about.com. - person ; 02.10.2009

Я думаю, вы могли бы использовать более компилятивный подход. Несколько недель назад я получил болгарскую базу данных, которая была динамически закодирована в БД, но при перемещении ее в другую базу данных я получил фанк ???

Я решил это путем сброса базы данных, настройки базы данных на сортировку utf8 и последующего импорта данных как двоичных. Это автоматически конвертировало все в utf8 и больше мне не давало ???.

Это было в MySQL

person Gus    schedule 02.10.2009
comment
мм, звучит хорошо! Как именно вы импортируете данные как двоичную часть? Возможно ли это через phpmyadmin? - person pixeline; 02.10.2009
comment
Извините, я долго не отвечал, меня не было. Это возможно через phpmyadmin i38.tinypic.com/1z8cgj.jpg - person Gus; 08.10.2009
comment
Привет, Гас. Спасибо, что ответили мне. Я попробовал и не повезло. Беатрис по-прежнему оказывается Баатрис как в старой, так и в новой базе данных. - person pixeline; 09.10.2009

Когда вы подключаетесь к базе данных, не забывайте всегда использовать mysql_set_charset ('utf8', $ db_connection);

он все исправит, он решил все мои проблемы.

См. Это: http://phpanswer.com/store-french-characters-into-mysql-db-and-display/

person cristian    schedule 15.08.2010

Как вы сказали, ваши данные иногда преобразуются с использованием utf8_encode, ваши данные кодируются либо с помощью UTF-8, либо с помощью ISO 8859-1 (поскольку utf8_encode преобразуется из ISO 8859-1 в UTF-8). А поскольку UTF-8 кодирует символы от 128 до 255 двумя байтами, начиная с 1100001x, вам просто нужно проверить, являются ли ваши данные действительными UTF-8, и преобразовать их, если нет.

Так что просканируйте все свои данные, если это уже UTF-8 (см. Несколько is_utf8 функций), и используйте utf8_encode, если это не UTF-8.

person Gumbo    schedule 01.10.2009
comment
привет Гамбо, я обновил свой вопрос с первой (неудачной попытки). Подскажите пожалуйста, посмотрите и посоветуйте? - person pixeline; 01.10.2009

Моя проблема в том, что каким-то образом я получил в своей базе данных такие символы, как à, é, ê в простом формате или в кодировке utf8. После расследования я пришел к выводу, что какой-то браузер (я не знаю IE, FF или другой) кодирует отправленные входные данные, поскольку для обработки форм отправки намеренно не добавлена ​​кодировка utf8. Итак, если я буду читать данные с помощью utf8_encode, я изменю другие простые символы, и наоборот.

Мое решение после изучения решений, приведенных выше: 1. Я создал новую базу данных с кодировкой utf8 2. Импортировал базу данных ПОСЛЕ того, как я изменил определение кодировки в операторе CREATE TABLE в файле дампа sql с Latin .... на UTF8. 3. импортировать данные из исходной базы данных (до этого момента, возможно, будет достаточно просто изменить кодировку в существующих базах данных и таблицах, и это только в том случае, если исходная база данных не является utf8) 4. обновить содержимое в базе данных напрямую, заменив символы в кодировке utf8 на там простой формат что-то вроде

UPDATE `clients` SET `name` = REPLACE(`name`,"é",'é' )  WHERE `name` LIKE CONVERT( _latin1 '%é%' USING utf8 ); 
  1. Я поместил в класс db (для кода php) эту строку, чтобы убедиться, что это сообщение UTF8

    $ this-> query ('УСТАНОВИТЬ СИМВОЛ UTF8');

Итак, как обновить? (шаг 4) Я построил массив с возможными символами, которые могут быть закодированы

$special_chars = array(
  'ù','û','ü',
  'ÿ',
  'à','â','ä','å','æ',
  'ç',
  'é','è','ê','ë',
  'ï','î',
  'ô','','ö','ó','ø',
  'ü');

Я создал массив с парами таблиц, поля, которые следует обновить

$where_to_look = array(
    array("table_name" , "field_name"),
        ..... );

чем,

    foreach($special_chars as $char)
    {
      foreach($where_to_look as $pair)
      {
        //$table = $pair[0]; $field = $pair[1]
        $sql = "SELECT id , `" . $pair[1] . "` FROM " .$pair[0] . " WHERE `" . $pair[1] . "` LIKE CONVERT( _latin1 '%" . $char . "%' USING utf8 );";

    if($db->num_rows() > 0){
         $sql1 = "UPDATE " . $pair[0] . " SET `" . $pair[1] . "` = REPLACE(`" . $pair[1] . "`,CONVERT( _latin1 '" . $char . "' USING utf8 ),'" . $char . "' )  WHERE `" . $pair[1] . "` LIKE CONVERT( _latin1 '%" . $char . "%' USING utf8 )";
         $db1->query($sql1);
        }
    }
 }

Основная идея - использовать функции кодирования mysql, чтобы избежать кодирования между mysql, apache, browser и обратно; ПРИМЕЧАНИЕ: у меня не было доступных функций php, таких как mb _....

Лучший

person didi    schedule 23.10.2009