кодировка strlen() и UTF-8

предполагая кодировку UTF-8 и strlen () в PHP, возможно ли, что эта строка имеет длину 4?

меня интересует только strlen (), а не другие функции

это строка: 1ï $¿½2

я протестировал его на своем компьютере, и я проверил кодировку UTF-8, и ответ, который я получаю, - 6.

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

PS: этот вопрос и ответ (4) исходит из макетного теста для ZCE, который я купил на Ebay.

PPS:пожалуйста, бросьте мне кость и проголосуйте за это. Я сделала домашнее задание. Заранее благодарю за все ответы и голоса.

6 ответов


строка, которую вы разместили, имеет шесть символов: $1�2 (знак доллара, цифра один, нижний регистр i с диаэрезисом, перевернутый вопросительный знак, одна половина дроби, цифра два)

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

однако, если бы мы должны были хранить эту строку как ISO 8859-1 или CP1252, у нас была бы шестибайтовая длинная последовательность, которая будьте легальны, как UTF-8. Переинтерпретация этих 6 байтов как UTF-8 приведет к 4 символам: $1�2 (знак доллара, цифра один, символ замены Юникода, цифра 2). То есть кодировка UTF-8 одного символа " � "идентична кодировке ISO-8859-1 трех символов"ï½½".

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

похоже, что исходная строка была обработана через несколько слои неправильной интерпретации; с помощью декодера UTF-8 на данных, отличных от UTF-8 (производя $1�2), а затем тем, что вы использовали для анализа этих данных (производя $1�2).


Как насчет использования mb_strlen() ?

http://lt.php.net/manual/en/function.mb-strlen.php

но если вам нужно использовать strlen, можно настроить веб-сервер, установив mbstring.директива func_overload до 2, поэтому она автоматически заменит использование strlen на mb_strlen в ваших скриптах.


необходимо использовать Многобайтовую строковую функцию mb_strlen () как:

mb_strlen($string, 'UTF-8');

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

последовательность � получается, когда вы кодируете замена символа U+FFFD ( � ) в UTF-8 и интерпретировать результат в latin1. Этот символ используется в качестве замены для байтовых последовательностей, которые не кодируют символ, когда например, чтение текста из файла. То, что произошло, вероятно, таково:

исходный вопрос, хранящийся в текстовом файле latin1, имел: ¢2 (вы можете заменить ¢ на любой символ без ASCII)

файл был прочитан программой, которая использовала UTF-8. Поскольку байт, соответствующий¢, не мог быть интерпретирован, программа заменила его и прочитала текст �2. Затем этот текст был написан с использованием UTF-8, в результате чего \xEF\xBF\xBD2 в файле.

потом какой-то третий приходит программа, которая читает файл в latin1 и показывает �2.


нет.

Я буду использовать доказательство противоречием.

strlen подсчитывает байты, поэтому с strlen 4, должно быть ровно 4 байта в этой строке.

кодировка UTF8 требуется не менее 1 байта на символ.

установлено, что:

  1. есть 4 байт
  2. персонаж представлен не менее, чем 1 байт

...тем не менее, у нас есть 6 письмена....это противоречие. Так что нет.

однако не совсем ясно, какой набор символов использует программное обеспечение для отображения (например, веб-браузер) для ввода строки. Он может использовать некоторую необычную схему кодирования, где символ может быть представлен менее чем 8 битами. Если это так, то 4 байта могут отображаться как 6 символов. Таким образом, строка может быть utf8, но браузер может решить интерпретировать ее как, скажем, некоторый 5-битный набор символов.


многие символы UTF-8 занимают несколько байтов вместо одного. Вот как построен UTF-8 (Вот как вы можете иметь так много символов в одном наборе).

попробовать mb_strlen() вместо.