Проблема кодирования UTF8 – с хорошими примерами

У меня есть следующая проблема кодирования символов, так как мне удалось сохранить данные с различной кодировкой символов в моей базе данных (UTF8). В приведенном ниже коде и выводах показаны две строки примеров и их вывод. 1 из них нужно будет заменить на UTF8, а другой уже есть.

Как я / должен ли я проверять, следует ли кодировать строку или нет? например, мне нужно, чтобы каждая строка выводилась правильно, поэтому как проверить, является ли она уже utf8, или нужно ли ее преобразовать?

Я использую PHP 5.2, таблицы mysql myisam:

CREATE TABLE IF NOT EXISTS `entities` ( .... `title` varchar(255) NOT NULL .... ) ENGINE=MyISAM DEFAULT CHARSET=utf8; <?php $text = $entity['Entity']['title']; echo 'Original : ', $text."<br />"; echo 'UTF8 Encode : ', utf8_encode($text)."<br />"; echo 'UTF8 Decode : ', utf8_decode($text)."<br />"; echo 'TRANSLIT : ', iconv("ISO-8859-1", "UTF-8//TRANSLIT", $text)."<br />"; echo 'IGNORE TRANSLIT : ', iconv("ISO-8859-1", "UTF-8//IGNORE//TRANSLIT", $text)."<br />"; echo 'IGNORE : ', iconv("ISO-8859-1", "UTF-8//IGNORE", $text)."<br />"; echo 'Plain : ', iconv("ISO-8859-1", "UTF-8", $text)."<br />"; ?> 

Выход 1:

 Original : France Télécom UTF8 Encode : France Télécom UTF8 Decode : France T l com TRANSLIT : France Télécom IGNORE TRANSLIT : France Télécom IGNORE : France Télécom Plain : France Télécom 

Результат 2: ###

 Original : Cond  Nast Publications UTF8 Encode : Condé Nast Publications UTF8 Decode : Cond?ast Publications TRANSLIT : Condé Nast Publications IGNORE TRANSLIT : Condé Nast Publications IGNORE : Condé Nast Publications Plain : Condé Nast Publications 

Спасибо вам за это. Кодировка символов, и я не очень хорошо себя чувствую!

ОБНОВИТЬ:

 echo strlen($string)."|".strlen(utf8_encode($string))."|"; echo (strlen($string)!==strlen(utf8_encode($string))) ? $string : utf8_encode($string); echo "<br />"; echo strlen($string)."|".strlen(utf8_decode($string))."|"; echo (strlen($string)!==strlen(utf8_decode($string))) ? $string : utf8_decode($string); echo "<br />"; 23|24|Cond  Nast Publications 23|21|Cond  Nast Publications 16|20|France Télécom 16|14|France Télécom 

Related of "Проблема кодирования UTF8 – с хорошими примерами"

Это может быть задачей для функции mb_detect_encoding() .

В моем ограниченном опыте с ним он не на 100% надежен, когда используется как общий «сниффер кодирования» – он проверяет наличие определенных символов и байтовых значений, чтобы сделать обоснованное предположение, – но в этом узком случае (ему нужно будет различать только между UTF-8 и ISO-8859-1), он должен работать.

 <?php $text = $entity['Entity']['title']; echo 'Original : ', $text."<br />"; $enc = mb_detect_encoding($text, "UTF-8,ISO-8859-1"); echo 'Detected encoding '.$enc."<br />"; echo 'Fixed result: '.iconv($enc, "UTF-8", $text)."<br />"; ?> 

вы можете получить неверные результаты для строк, которые не содержат специальных символов, но это не проблема.

Я сделал функцию, которая затрагивает все эти проблемы. Он называется Encoding :: toUTF8 ().

 <?php $text = $entity['Entity']['title']; echo 'Original : ', $text."<br />"; echo 'Encoding::toUTF8 : ', Encoding::toUTF8($text)."<br />"; ?> 

Вывод:

 Original : France Télécom Encoding::toUTF8 : France Télécom Original : Cond  Nast Publications Encoding::toUTF8 : Condé Nast Publications 

Вам не нужно знать, что такое кодировка ваших строк, если вы знаете, что это либо на Latin1 (iso 8859-1), либо на Windows-1252, либо на UTF8. Строка также может содержать их смесь.

Кодирование :: toUTF8 () преобразует все в UTF8.

Я сделал это, потому что служба давала мне поток данных, все испорченные, смешивая UTF8 и Latin1 в одной строке.

Применение:

 $utf8_string = Encoding::toUTF8($utf8_or_latin1_or_mixed_string); $latin1_string = Encoding::toLatin1($utf8_or_latin1_or_mixed_string); 

Скачать:

http://dl.dropbox.com/u/186012/PHP/forceUTF8.zip

Я включил еще одну функцию, Encoding :: fixUFT8 (), которая исправит каждую строку 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 

Другой способ, возможно, более быстрый и менее ненадежный:

 echo (strlen($str)!==strlen(utf8_decode($str))) ? $str //is multibyte, leave as is : utf8_encode($str); //encode 

Он сравнивает длину исходной строки и строку utf8_decoded. Строка, содержащая многобайтовый символ, имеет параметр strlen, который отличается от аналогичного strben с одним байтом.

Например:

 strlen('Télécom') 

должен вернуть 7 в Latin1 и 9 в UTF8

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

 SET NAMES UTF8; 

Это стандарт SQL Standard и хорошо работает с другими базами данных, такими как Firebird и PostgreSQL.

Но помните, что вам нужно также обеспечить декларации UTF-8 в других местах, чтобы ваше приложение отлично работало. Следуйте за быстрым контрольным списком.

  • Все файлы должны быть сохранены как UTF-8 (желательно без спецификации [Маска байтового байта])
  • Ваш HTTP-сервер должен отправить заголовок кодировки UTF-8. Используйте Firebug или Live HTTP Headers для проверки.
  • Если ваш сервер сжимает и / или выполняет токенизацию ответа, вы можете увидеть содержимое заголовка как chunked или gzipped. Это не проблема, если вы сохраняете файлы как UTF-8 и
  • Объявите кодировку в HTML-заголовке, используя соответствующий метатег.
  • По всем приложениям (сокетам, файловой системе, базам данных …) не забывайте каждый раз указывать UTF-8. Выполняя это при открытии соединения с базой данных или, таким образом, вам не нужно постоянно кодировать / декодировать / отлаживать. Grab'em от root.

Я сделал эти маленькие 2 функции, которые хорошо работают с обнаружением / конверсией UTF-8 и ISO-8859-1 …

 function detect_encoding($string) { //http://w3.org/International/questions/qa-forms-utf-8.html if (preg_match('%^(?: [\x09\x0A\x0D\x20-\x7E] | [\xC2-\xDF][\x80-\xBF] | \xE0[\xA0-\xBF][\x80-\xBF] | [\xE1-\xEC\xEE\xEF][\x80-\xBF]{2} | \xED[\x80-\x9F][\x80-\xBF] | \xF0[\x90-\xBF][\x80-\xBF]{2} | [\xF1-\xF3][\x80-\xBF]{3} | \xF4[\x80-\x8F][\x80-\xBF]{2} )*$%xs', $string)) return 'UTF-8'; //If you need to distinguish between UTF-8 and ISO-8859-1 encoding, list UTF-8 first in your encoding_list. //if you list ISO-8859-1 first, mb_detect_encoding() will always return ISO-8859-1. return mb_detect_encoding($string, array('UTF-8', 'ASCII', 'ISO-8859-1', 'JIS', 'EUC-JP', 'SJIS')); } function convert_encoding($string, $to_encoding, $from_encoding = '') { if ($from_encoding == '') $from_encoding = detect_encoding($string); if ($from_encoding == $to_encoding) return $string; return mb_convert_encoding($string, $to_encoding, $from_encoding); } 

Если ваша база данных содержит строки в двух разных кодировках, то я бы сделал это вместо того, чтобы преследовать весь ваш код приложения с помощью обнаружения / преобразования charset, чтобы написать сценарий «один выстрел», который будет читать все ваши записи в таблицах и обновлять их строки до правильного (я бы выбрал UTF-8, если бы я был вами). Таким образом, ваш код будет чище и проще в обслуживании.

Просто записывайте записи циклов в каждую таблицу вашей базы данных и конвертируйте строки следующим образом:

 //if the 3rd param is not specified the "from encoding" is detected automatically $newString = convert_encoding($oldString, 'UTF-8'); 
  1. Какую базу данных вы используете?
  2. Вам нужно знать кодировку исходной строки, прежде чем преобразовать ее в utf-8, если она находится в ISO-8859-1 (latin1), тогда самый простой способ utf8_encode (), иначе вам нужно использовать либо icov, либо mbstring lib для конвертировать, и оба из них должны знать кодировку ввода для правильного скрытия.
  3. Вы указываете свою базу данных о кодировке при вставке / выборе данных?