Может быть несколько причин, по которым строка может содержать недопустимые кодовые единицы . Чтобы понять, почему это может произойти, вам сначала нужно понять, что такое кодовая единица и чем она отличается от кодовой точки.
Стандарт Unicode определяет список кодовых точек, что в простых терминах означает, что каждый символ, который вам понадобится, должен иметь четко определенный идентификатор. Следовательно, кодовая точка - это уникальный идентификатор для конкретного символа в стандарте Unicode. Он определяет 1,114,112 кодовых точек на 17 плоскостях.
Юникод может быть реализован различными кодировками символов. Стандарт Unicode определяет UTF-8, UTF-16 и UTF-32, а также используется несколько других кодировок. Наиболее часто используемые кодировки - это UTF-8, UTF-16 и UCS-2, предшественник UTF-16. Каждое кодирование будет генерировать различную кодовую единицу для кодирования конкретной кодовой точки.
Максимальное количество, которое вы можете сохранить в байте, равно 255, и вы можете видеть, что количество кодовых точек значительно превышает максимальное количество, которое вы можете сохранить в одном байте. Именно здесь приходят упомянутые выше многобайтовые кодировки. Я рекомендую читать о них больше в свободное время, но для простоты я буду говорить о UTF-8 только с этого момента.
UTF-8 - кодировка переменной длины. Это означает, что для кодирования буквы A
, например, вам нужен только 1 байт, в отличие от, например, ?
, который использует 4 байта. Чтобы узнать, какой байт в последовательности строк является частью многобайтовой последовательности, вам нужны префиксные коды. Первый байт указывает количество байтов в последовательности. Все байты составляют единицу кода для этого символа. Неправильный символ не будет декодирован, если поток заканчивается в середине последовательности. Отдельный байт из единицы кода сам по себе является недопустимой единицей кода ; он не может быть декодирован, чтобы указывать на правильный код Unicode. Посмотрите, что происходит после 7F . Если вы сравните это с исходным кодом PHP , вы можете ясно увидеть, что если вы встретите байт в диапазоне 0x80 https://en.wikipedia.org/wiki/UTF-8#Description
Благодаря UTF-16 некоторые кодовые точки также могут быть недействительными единицами кода. Они называются суррогатами и сами по себе не представляют символ Unicode.
Строка может быть искажена по разным причинам, но возможно иметь недопустимых байтовых последовательностей, то есть кодовых единиц
Некоторые примеры недопустимых последовательностей кодовых единиц:
"\xED\x9F\xC0"
- суррогатное
"\x80"
"\xC2\x79"
"\xC3\xC0"
и так далее ...