mb_detect_encoding() в php

Прежде всего, я хотел бы сказать, что я прочитал другой пост о mb_detect_encoding php в Странное поведение mb_detect_order() в PHP. Что определенно подтверждает то, что я узнал путем проб и ошибок. однако есть еще несколько вещей, которые меня смущают.

Я создаю html-скребки в основном англоязычных сайтов, которые собирают данные и сохраняют их в XML UTF-8. Я столкнулся с проблемой, когда сама страница объявляет кодировку ISO-8859-1, но содержит символы, уникальные для Windows-1252. в частности, правильная одинарная кавычка (’) 0x92. Насколько я понимаю, windows-1252 является надмножеством iso-8859-1, что наводит меня на мысль, зачем вообще использовать utf8_encode()? почему бы просто не использовать iconv('Windows-1252', 'UTF-8', $str) вместо utf8_encode(), поскольку все, что представлено в iso-8859-1, будет преобразовано, а также символы, уникальные для windows-1252 ( т. е. €‚ƒ' ' "")

Также

$ansi = "€";//euro mark, the code file itself is in ansi

$detected = mb_detect_encoding($ansi, "WINDOWS-1252");// $detected == "Windows-1252"
$detected = mb_detect_encoding('a'.$ansi, "WINDOWS-1252");// $detected == FALSE
$detected = mb_detect_encoding($ansi.'a', "WINDOWS-1252");// $detected == "Windows-1252"
$detected = mb_detect_encoding($ansi.'a', "WINDOWS-1252",TRUE);// $detected == FALSE

почему это происходит? если первый символ в строке не windows-1252, даже если остальная часть есть, он терпит неудачу? Разве такое поведение не делает его довольно бесполезным? насколько различаются iso-8859-1 и windows-1252

другая вещь, которая меня смущала, была, скажем, я хочу обнаружить кодировку между ASCII, ISO-8859-1, windows-1252, UTF-8. Можно ли обнаружить строки таким образом, чтобы получить набор с самым низким рейтингом? (т.е.

$ascii = "123"; // desired detect result == 'ASCII'
$iso = "é".$ascii; // desired detect result == 'ISO-8859-1'
$ansi = "€".$iso; // desired detect result == 'Windows-1252'
$utf8 = file_get_contents('utf8.txt', true);//$utf8 == '你好123é€', desired detect result == 'UTF-8'

мой $detect_order = array('ASCII', 'ISO-8859-1', 'Windows-1252','UTF-8'); Я знаю, что это неверно, так как это дало мне следующие результаты

$ascii == 'ASCII'
$iso   == 'ISO-8859-1'
$ansi  == 'ISO-8859-1'
$utf8  == 'ISO-8859-1'

почему мой порядок обнаружения ('ASCII', 'ISO-8859-1', 'Windows-1252', 'UTF-8') неверен для того, что я хочу получить?

ближайшее желаемое возвращаемое значение, которое я получил, было

$ascii == 'ASCII'
$iso   == 'ISO-8859-1'
$ansi  == 'ISO-8859-1'
$utf8  == 'UTF-8'

оба следующих массива mb_detect_order дали мне вышеуказанные значения

$detect_order = array('ASCII', 'UTF-8', 'Windows-1252', 'ISO-8859-1');
$detect_order = array('ASCII', 'UTF-8', 'ISO-8859-1', 'Windows-1252');

это сбивает меня с толку!

фу, может кто-нибудь пролить свет на это? спасибо большое оценил!


person george H    schedule 17.11.2011    source источник


Ответы (3)


Это известная ошибка.

Windows-1251 и Windows-1252 будут успешными только в том случае, если вся строка состоит из старших байтов в определенном диапазоне. Это означает, что вы никогда не получите правильное преобразование, потому что текст будет отображаться как ISO-8859-1, даже если это Windows-1252.

Я столкнулся с этой проблемой при преобразовании из LATIN1 в UTF-8. У меня было много содержимого, вставленного из Microsoft Word и сохраненного в поле VARCHAR с использованием кодировки LATIN1 таблицы MySQL. Как вы, наверное, знаете, Word преобразует апострофы и кавычки в умные апострофы и фигурные кавычки. Ни один из них не будет отображаться на экране, потому что эти символы не были должным образом преобразованы. Текст всегда определялся как ISO-8859-1. Чтобы решить проблему, я принудительно преобразовал Windows-1252 в UTF-8, и апострофы и кавычки (и другие символы) были правильно преобразованы.

person noun    schedule 11.06.2014

Не уверен, что отвечу на все ваши вопросы, но вот:

Насколько я понимаю, windows-1252 является надмножеством iso-8859-1, что наводит меня на мысль, зачем вообще использовать utf8_encode()? почему бы просто не использовать iconv('Windows-1252', 'UTF-8', $str) вместо utf8_encode(), поскольку все, что представлено в iso-8859-1, будет преобразовано, а также символы, уникальные для windows-1252

Не стоит заморачиваться с ut8_encode. Перейдите к iconv() или mb_convert_encoding. ut8_encode преобразует только ISO-8859-1 в UTF-8. если вам нужно преобразовать между различными кодировками, вы должны использовать другие функции.

Относительно марки евро. Не уверен, что это было добавлено (официально или неофициально) в ISO-8859-1 в какой-то момент, но оба утверждения ниже возвращают true

$ansi = "€";//euro mark, the code file itself is in ansi

$detected = mb_detect_encoding($ansi, "WINDOWS-1252", TRUE);// $detected == "Windows-1252"
echo $detected."<br/>-<br/>";
$detected = mb_detect_encoding($ansi, "ISO-8859-1", TRUE);// $detected == ISO-8859-1
echo $detected."<br/>-<br/>";


$detected = mb_detect_encoding($ansi, "WINDOWS-1252");// $detected == "Windows-1252"
echo $detected."<br/>-<br/>";
$detected = mb_detect_encoding($ansi, "ISO-8859-1");// $detected == ISO-8859-1
echo $detected."<br/>-<br/>";

Обратите внимание, это результат, когда для параметра strict установлено значение True или False. Это может объяснить, почему

мой $detect_order = array('ASCII', 'ISO-8859-1', 'Windows-1252','UTF-8'); Я знаю, что это неверно, так как это дало мне следующие результаты

дает вам ISO-8859-1. Я заметил, что вы переключили UTF-8 перед ISO в последнем порядке, поэтому в конце он дал вам UTF-8.

почему мой порядок обнаружения ('ASCII', 'ISO-8859-1', 'Windows-1252', 'UTF-8') неверен для того, что я хочу получить?

На сайте php http://us3.php.net/manual/en/function.mb-detect-order.php, установка ISO перед UTF-8 всегда будет возвращать ISO. Проверьте их бесполезный пример порядка обнаружения.

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

$detect_order = array('ASCII', 'UTF-8', 'Windows-1252', 'ISO-8859-1'); $detect_order = array('ASCII', 'UTF-8', 'ISO-8859-1', 'Windows-1252');

person Alexey Gerasimov    schedule 17.11.2011
comment
Алексей спс за ответ! на самом деле $ansi = €‚ƒ„…†‡ˆ‰Š‹ŒŒŽ‘’“”•–—˜™š›œžŸ;// все символы уникальны для windows-1252. $utf8 = '你好123é€';//file_get_content из файла с кодировкой UTF8 $detected = mb_detect_encoding($utf8, ISO-88591, UTF-8); Ожидается $detected == UTF-8, поскольку ISO-8859-1 является однобайтовым и не может отображать символы MB, такие как китайские символы. Однако, как вы сказали, веб-сайт PHP утверждает обратное. Я в замешательстве, почему это? Как отличить ISO-8859-1 от UTF-8? каков правильный порядок обнаружения, если не ISO-88591, UTF-8? любой другой порядок был бы нелогичным, нет? - person george H; 18.11.2011
comment
@GeorgeH, поместите UTF-8 перед ISO в порядке обнаружения, и имеющаяся у вас строка $utf8 будет обнаружена как UTF-8. Пример: $utf8=你好123é€; $detect_order = массив('UTF-8', 'ISO-8859-1'); $detected = mb_detect_encoding($utf8, $detect_order);// $detected == UTF-8 - person Alexey Gerasimov; 18.11.2011
comment
Я знаю, что это старая тема, но она была полезна мне в недавней ситуации. Порядок важен, потому что Windows-1252 и ISO-8859 будут соответствовать почти любой строке байтов, за исключением, возможно, диапазона управляющих символов. UTF-8 имеет более строгие правила и должен быть проверен в первую очередь, но кажется, что он работает правильно, только если вы используете strict=true в mb_detect_encoding. Кроме того, ASCII является подмножеством трех других стандартов и может быть не так полезен для обнаружения. - person gordonwd; 04.12.2012
comment
По сути, gordonwd прав, но в PHP Windows-1252 почти никогда не будет обнаружена, потому что, как только ваш текст содержит какие-либо символы за пределами от 0x80 до 0x9f, он считается недействительным Windows-1252. Это означает, что если ваша строка содержит обычную букву ASCII, такую ​​как A, или даже символ пробела, PHP скажет, что это недопустимо для Windows-1252. Это ошибка PHP, см. bugs.php.net/bug.php?id=64667. . - person scy; 23.04.2014

символ € не является частью кодировки utf8!

вы должны поставить его как !

или кодировать в windows-1252 или iso-8859-15 (то же самое, что и iso-8859-1, но с символом €)

person Ismael Miguel    schedule 22.12.2012