WedX - журнал о программировании и компьютерных науках

Как обнаружить искаженную строку utf-8 в PHP?

Функция iconv иногда выдает ошибку:

Notice:
iconv() [function.iconv]:
Detected an incomplete multibyte character in input string in [...]

Есть ли способ определить, что в строке utf-8 есть недопустимые символы, прежде чем помещать данные в inconv?

17.07.2011


Ответы:


1

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

Вы можете использовать проверку достоверности UTF-8, доступную в preg_match [PHP Manual] начиная с PHP 4.3.5. Он вернет 0 (без дополнительной информации), если указана недопустимая строка:

$isUTF8 = preg_match('//u', $string);

Другой вариант: mb_check_encoding [Руководство по PHP]:

$validUTF8 = mb_check_encoding($string, 'UTF-8');

Вы также можете использовать другую функцию: mb_detect_encoding [Руководство по PHP]< /sup>:

$validUTF8 = ! (false === mb_detect_encoding($string, 'UTF-8', true));

Важно установить для параметра strict значение true.

Кроме того, iconv [Руководство по PHP] позволяет вам изменять/удалять недопустимые последовательности на лету. (Однако, если iconv встречает такую ​​последовательность, он генерирует уведомление; это поведение нельзя изменить.)

echo 'TRANSLIT : ', iconv("UTF-8", "ISO-8859-1//TRANSLIT", $string), PHP_EOL;
echo 'IGNORE   : ', iconv("UTF-8", "ISO-8859-1//IGNORE", $string), PHP_EOL;

Вы можете использовать @ и проверить длину возвращаемой строки:

strlen($string) === strlen(@iconv('UTF-8', 'UTF-8//IGNORE', $string));

Также проверьте примеры на странице руководства iconv.

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

17.07.2011
  • вы не ошиблись, но кажется, что preg_match('!.!u', $str) делает свое дело - он молча проверяет, является ли str utf-8, прежде чем пытаться что-либо найти. - эта точка в регулярном выражении даже не нужна 17.07.2011
  • @ user393087: Я внес небольшое изменение, чтобы метод preg_match правильно работал и с пустыми строками. 17.07.2011
  • @hakre: Спасибо за хороший контент. 28.03.2015
  • Хороший обзор всех вариантов! Я написал микротест, чтобы увидеть, что быстрее — preg_match() кажется самым быстрым в целом (в PHP 7) как для действительных/недействительных, так и для коротких/длинных строк. 20.07.2016
  • Отличный ответ! Стоит отметить, что вы также можете проверить сценарии, которым принадлежат символы Юникода, поэтому эта строка Àbcdeឃ не будет соответствовать /^\p{Latin}*$/u, но будет соответствовать /^[\p{Latin}\p {кхмерский}]*$/ед. В руководстве по php перечислены различные поддерживаемые скрипты. 10.09.2018
  • Когда я запускаю метод preg, я получаю false с preg_last_error() === PREG_BAD_UTF8_ERROR. Документация не очень ясна по этому поводу, но есть ли шанс, что поведение было недавно изменено? 25.06.2019
  • @Bananaapple: функции preg_... в PHP используют библиотеку PCRE, и в случае этой ошибки константа PHP отражает код ошибки из библиотеки PCRE (PCRE_ERROR_BADUTF8). В PHP 7.3 реализована внутренняя миграция с PCRE на PCRE2. Независимо от того, какую версию PHP вы используете, вы можете проверить используемую версию библиотеки PCRE, проверив константу PCRE_VERSION и/или phpinfo(). Это может выявить изменения. Технические подробности см. на pcre.org/current/doc/html/pcre2unicode.html для ошибок в строках UTF-8. 25.06.2019

  • 2

    Вы можете попробовать использовать mb_detect_encoding, чтобы определить, есть ли у вас другой набор символов (отличный от UTF-8), а затем mb_convert_encoding для преобразования в UTF-8, если это необходимо. Более вероятно, что люди дают вам действительный контент в другом наборе символов, чем дают вам недопустимый UTF-8.

    17.07.2011
  • Имейте в виду, что допустимые строки ASCII также являются допустимыми строками UTF8. Это означает, что mb_detect_encoding будет возвращать ASCII для любой строки, которая является допустимой строкой UTF8 и не содержит символов Unicode. 16.01.2017

  • 3

    Спецификация недопустимых символов в UTF-8 довольно ясна. Вы, вероятно, захотите удалить их, прежде чем пытаться разобрать его. Их не должно быть, поэтому, если бы вы могли избежать этого даже до создания XML, это было бы еще лучше.

    См. здесь для справки:

    https://www.w3.org/TR/xml/#charsets

    Это не полный список, многие синтаксические анализаторы также запрещают некоторые управляющие символы с низкими номерами, но я не могу найти полный список прямо сейчас.

    Однако у iconv может быть встроенная поддержка для этого:

    https://www.zeitoun.net/articles/clear-invalid-utf8/start

    17.07.2011

    4

    поместите @ перед iconv(), чтобы подавить УВЕДОМЛЕНИЕ, и //IGNORE после UTF-8 в идентификаторе исходной кодировки, чтобы игнорировать недопустимые символы:

    @iconv( 'UTF-8//IGNORE', $destinationEncoding, $yourString );
    
    17.07.2011
  • Я знаю, как его игнорировать, я не знаю, как его обнаружить, я не хочу молча передавать его по моему коду. 17.07.2011
  • Кстати, решение preg_match() в другом вопросе очень интересно, я бы согласился с этим. 17.07.2011
  • Новые материалы

    Объяснение документов 02: BERT
    BERT представил двухступенчатую структуру обучения: предварительное обучение и тонкая настройка. Во время предварительного обучения модель обучается на неразмеченных данных с помощью..

    Как проанализировать работу вашего классификатора?
    Не всегда просто знать, какие показатели использовать С развитием глубокого обучения все больше и больше людей учатся обучать свой первый классификатор. Но как только вы закончите..

    Работа с цепями Маркова, часть 4 (Машинное обучение)
    Нелинейные цепи Маркова с агрегатором и их приложения (arXiv) Автор : Бар Лайт Аннотация: Изучаются свойства подкласса случайных процессов, называемых дискретными нелинейными цепями Маркова..

    Crazy Laravel Livewire упростил мне создание электронной коммерции (панель администратора и API) [Часть 3]
    Как вы сегодня, ребята? В этой части мы создадим CRUD для данных о продукте. Думаю, в этой части я не буду слишком много делиться теорией, но чаще буду делиться своим кодом. Потому что..

    Использование машинного обучения и Python для классификации 1000 сезонов новичков MLB Hitter
    Чему может научиться машина, глядя на сезоны новичков 1000 игроков MLB? Это то, что исследует это приложение. В этом процессе мы будем использовать неконтролируемое обучение, чтобы..

    Учебные заметки: создание моего первого пакета Node.js
    Это мои обучающие заметки, когда я научился создавать свой самый первый пакет Node.js, распространяемый через npm. Оглавление Глоссарий I. Новый пакет 1.1 советы по инициализации..

    Забудьте о Matplotlib: улучшите визуализацию данных с помощью умопомрачительных функций Seaborn!
    Примечание. Эта запись в блоге предполагает базовое знакомство с Python и концепциями анализа данных. Привет, энтузиасты данных! Добро пожаловать в мой блог, где я расскажу о невероятных..


    Для любых предложений по сайту: [email protected]