mb_convert_encoding - php windows-1251 to utf-8




PHP: конвертировать любую строку в UTF-8 без знания исходного набора символов или, по крайней мере, попробовать (7)

Основная проблема для меня в том, что я не знаю, какая кодировка будет источником любой строки - она ​​может быть из текстового поля (использование полезно только в том случае, если пользователь действительно отправил форму), или это может быть из загруженного текстового файла, поэтому я действительно не контролирую ввод.

Я не думаю, что это проблема. Приложение знает источник ввода. Если это из формы, используйте кодировку UTF-8 в вашем случае. Это работает. Просто убедитесь, что предоставленные данные правильно закодированы (проверка). Имейте в виду, что не все базы данных поддерживают UTF-8 в полном объеме.

Если это файл, вы не сохраните его в кодировке UTF-8 в базе данных, а в двоичной форме. Когда вы снова выводите файл, используйте также двоичный вывод, тогда это полностью прозрачно.

Ваша идея хорошая, что пользователь может сказать кодировку, если он / она все равно сможет сказать, загрузив файл, так как он двоичный.

Поэтому я должен признать, что я не вижу конкретной проблемы, которую вы поднимаете с вашим вопросом. Но, возможно, вы можете добавить несколько подробностей о вашей проблеме.

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

Основная проблема для меня в том, что я не знаю, какая кодировка источника любой строки будет - она ​​может быть из текстового поля (использование <form accept-charset="utf-8"> полезно, только если пользователь фактически отправил форму), или это может быть из загруженного текстового файла, поэтому я действительно не контролирую ввод.

Мне нужна функция или класс, который гарантирует, что материал, поступающий в мою базу данных, является, насколько это возможно, кодировкой UTF-8. Я пробовал iconv(mb_detect_encoding($text), "UTF-8", $text); но у этого есть проблемы (если вход «fiancée», он возвращает «fianc»). Я пробовал много вещей = /

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

Я прочитал другие вопросы SO по этому вопросу, но они, похоже, имеют тонкие различия, такие как «Мне нужно разобрать RSS-каналы» или «Я удаляю данные с веб-сайтов» (или, действительно, «Вы не можете»).

Но должно быть что-то, что, по крайней мере, имеет хорошую попытку !


В родине России у нас есть 4 популярных кодировки, поэтому ваш вопрос здесь востребован.

Только символьные коды символов вы не можете обнаружить кодировку, потому что страницы кода пересекаются. Некоторые кодовые страницы на разных языках имеют даже полное пересечение. Итак, нам нужен другой подход .

Единственный способ работать с неизвестными кодировками - работать с вероятностями. Итак, мы не хотим отвечать на вопрос «что такое кодирование этого текста?», Мы пытаемся понять, « что, скорее всего, кодирует этот текст? ».

Один парень в популярном российском технологическом блоге изобрел такой подход:

Постройте диапазон вероятностей кодов символов в каждой кодировке, которую вы хотите поддерживать. Вы можете построить его, используя некоторые большие тексты на вашем языке (например, какую-нибудь фикцию, используйте Шекспир для английского и Толстого для русского, lol). Вы получите что-то вроде этого:

    encoding_1:
    190 => 0.095249209893009,
    222 => 0.095249209893009,
    ...
    encoding_2:
    239 => 0.095249209893009,
    207 => 0.095249209893009,
    ...
    encoding_N:
    charcode => probabilty

Следующий. Вы берете текст в неизвестной кодировке и для каждой кодировки в вашем «вероятностном словаре» вы ищете частоту каждого символа в тексте с неизвестным кодированием. Суммарная вероятность символов. Кодирование с большим рейтингом, вероятно, является победителем. Лучшие результаты для больших текстов.

Если вам интересно , я могу с радостью помочь вам в решении этой задачи. Мы можем значительно повысить точность, создав список вероятностей с двумя символами.

Btw. mb_detect_encoding certanly не работает. Да, вообще. Пожалуйста, посмотрите исходный код mb_detect_encoding в «ext / mbstring / libmbfl / mbfl / mbfl_ident.c».


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


Если вы хотите «взять это на консоль», я бы рекомендовал enca . В отличие от довольно упрощенного mb_detect_encoding , он использует «смесь разбора, статистического анализа, угадывания и черной магии для определения их кодировок» (lol - см. Справочную страницу ). Тем не менее, вы обычно должны передавать язык входного файла, если вы хотите определить такие кодировки для конкретной страны. (Тем не менее, mb_detect_encoding существу имеет то же требование, что и кодирование должно появиться «в нужном месте» в списке переданных кодировок, чтобы он мог быть обнаружен вообще).

enca также появился здесь: как найти кодировку файла в Unix с помощью скрипта (ов)


Кажется, что на ваш вопрос достаточно ответили, но у меня есть подход, который может упростить вам случай:

У меня была аналогичная проблема, пытающаяся вернуть строковые данные из mysql, даже настраивая как базу данных, так и php, чтобы возвращать строки, отформатированные в utf-8. Единственный способ получить ошибку - это фактически вернуть их из базы данных.

Наконец, проплывая через Интернет, я нашел очень простой способ справиться с этим:

Предоставляя вам возможность сохранять все эти типы строковых данных в вашем mysql в разных форматах и ​​сопоставлениях, вам нужно только, прямо в вашем файле подключения php, установить сопоставление в utf-8, например:

$connection = new mysqli($server, $user, $pass, $db);
$connection->set_charset("utf8");

Это означает, что сначала вы сохраняете данные в любом формате или сортировке, и конвертируете их только при возврате в ваш php-файл.

Надеюсь, это было полезно!


Невозможно идентифицировать кодировку строки, которая является полностью точной. Есть способы попытаться угадать кодировку. Один из этих способов и, вероятно, / в настоящее время лучший в PHP, это mb_detect_encoding (). Это сканирует вашу строку и ищет вхождения вещей, уникальных для определенных кодировок. В зависимости от вашей строки не может быть таких различимых случаев.

Возьмите кодировку ISO-8859-1 и ISO-8859-15 ( http://en.wikipedia.org/wiki/ISO/IEC_8859-15#Changes_from_ISO-8859-1 )

Есть только несколько разных персонажей, и, чтобы ухудшить их, они представлены теми же байтами. Невозможно обнаружить, получив строку, не зная, что это кодировка, должен ли байт 0xA4 обозначать ¤ или € в вашей строке, поэтому нет способа узнать, что это точная кодировка.

(Примечание: вы могли бы добавить человеческий фактор или еще более совершенную технологию сканирования (например, что предлагает Oroboros102), чтобы попытаться выяснить, основываясь на окружающем контексте, если персонаж должен быть ¤ или €, хотя это похоже на мост очень далеко)

Есть более различимые различия между UTF-8 и ISO-8859-1, поэтому все равно стоит попытаться понять это, когда вы не уверены, хотя вы можете и не должны полагаться на то, что это правильно.

Интересное чтение: http://kore-nordmann.de/blog/php_charset_encoding_FAQ.html#how-do-i-determine-the-charset-encoding-of-a-string

Однако есть и другие способы обеспечения правильной кодировки. Что касается форм, попробуйте максимально усилить UTF-8 (проверьте снеговика, чтобы убедиться, что вы будете представлять UTF-8 в каждом браузере: http://intertwingly.net/blog/2010/07/29/Rails-and-Snowmen ). Это делается, по крайней мере, вы можете быть уверены, что каждый текст, представленный через ваши формы, - utf_8. Что касается загруженных файлов, попробуйте запустить команду unix «file -i» на нем, например, exec () (если возможно, на вашем сервере), чтобы помочь обнаружению (используя спецификацию документа). Что касается скребущих данных, вы можете прочитать заголовки HTTP, которые обычно определяют кодировку. При анализе XML-файлов проверьте, содержат ли метаданные XML определение charset.

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


public function convertToUtf8($text) {
    if(!$this->html)
        $this->html = cURL('http://'.$this->url, array('timeout' => 15));

    $html = $this->html;
    preg_match('/<meta.*?charset=(|\")(.*?)("|\")/i', $html, $matches);

    $charset = $matches[2];

    if($charset)
        return mb_convert_encoding($text, 'UTF-8', $charset);
    else
        return $text;
}

Параметры по умолчанию cURL:

curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);

Я попробовал что-то вроде этого. Это помогло мне. Если вы найдете в мета-кодировке информацию, я конвертирую, иначе ничего не делаю.





character-encoding