Strlen() и UTF-8
Предполагая кодировку UTF-8 и strlen() в PHP, возможно ли, что эта строка имеет длину 4?
Мне интересно узнать о strlen(), а не о других функциях
Это строка: $1�2
Я тестировал его на своем собственном компьютере, и я проверил кодировку UTF-8, и ответ, который я получаю, равен 6.
Я не вижу ничего в руководстве для strlen или что-либо, что я читал на UTF-8, который объяснил бы, почему некоторые из вышеперечисленных символов будут считаться меньше одного.
PS: Этот вопрос и ответ (4) исходят из ложного теста для ZCE, который я купил на Ebay.
PPS: Пожалуйста, бросьте мне кость и проголосуйте за нее. Я сделал домашнее задание. Заранее благодарю всех ответов и голосов.
Ответы
Ответ 1
Строка, которую вы отправили, имеет длину шесть символов: $1�2 (знак доллара, цифра один, строчный регистр я с диарезисом, знак перевернутого вопроса, одна половина, цифра два)
Если strlen() вызывается с представлением UTF-8 этой строки, вы получите результат из девяти (вероятно, хотя есть несколько представлений с разной длиной).
Однако, если бы мы сохранили эту строку как ISO 8859-1 или CP1252, у нас была бы шестибайтная длинная последовательность, которая была бы законна как UTF-8. Интерпретация этих 6 байтов, как UTF-8, приведет к 4 символам: $1 2 (знак доллара, цифра один, символ замены Unicode, цифра 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 в ваших сценариях.
Ответ 3
необходимо использовать функцию многобайтовой строки mb_strlen(), например:
mb_strlen($string, 'UTF-8');
Ответ 4
Вероятно, что в какой-то момент между подготовкой вопроса и чтением его какой-то процесс исказил в нем не-ASCII-символы, поэтому вопрос был первоначально о некоторой строке с 4 символами в ней.
Последовательность �
получается при кодировании символа символа U + FFFD ( ) в UTF-8 и интерпретации результата в latin1. Этот символ используется в качестве замены байтовых последовательностей, которые не кодируют какого-либо символа при чтении текста из файла, например. Вероятно, произошло следующее:
Исходный вопрос, сохраненный в текстовом файле latin1, имел: $1¢2
(вы можете заменить ¢ любым символом, отличным от ASCII)
Файл был прочитан программой, использующей UTF-8. Поскольку байт, соответствующий ¢, не может быть интерпретирован, программа заменила его и прочитала текст $1�2
. Затем этот текст был выписан с использованием UTF-8, в результате получилось $1\xEF\xBF\xBD2
в файле.
Затем появляется какая-то третья программа, которая читает файл в latin1 и показывает $1�2
.
Ответ 5
Нет.
Я буду использовать доказательство от противного.
strlen подсчитывает байты, поэтому с strlen из 4 в этой строке должно быть ровно 4 байта.
Для кодирования UTF8 требуется не менее 1 байт на символ.
Мы установили, что:
- есть 4 байта
- символ представлен не менее чем 1 байт
... но у нас есть 6 символов.... что противоречие. Итак, нет.
Однако не совсем понятно, какой символ задает программное обеспечение для показа (например, веб-браузер), использующее intepret строку. Он может использовать какую-то необычную схему кодирования, где символ может быть представлен менее чем 8 бит. Если это так, то 4 байта могут отображаться как 6 символов. Таким образом, строка может быть utf8, но браузер может решить интерпретировать ее как, скажем, с 5-битным набором символов.
Ответ 6
Многие символы UTF-8 принимают несколько байтов вместо одного. Это как UTF-8 (так как вы можете иметь так много символов в одном наборе).
Попробуйте mb_strlen()
.