PHP-длина строки, содержащей emojis/специальные символы
Я создаю API для мобильного приложения, и у меня, похоже, есть проблема с подсчетом длины строки, содержащей emojis. Мой код:
$str = "
2 ответов
ваши функции все подсчитывают разные вещи.
Graphemes: ✌ ️ @ m e n t i o n 13
----------- ----------- -------- --------------------- ------ ------ ------ ------ ------ ------ ------ ------ ------
Code points: U+1F44D U+1F3FF U+270C U+1F3FF U+FE0F U+0020 U+0040 U+006D U+0065 U+006E U+0074 U+0069 U+006F U+006E 14
UTF-16 code units: D83D DC4D D83C DFFF 270C D83C DFFF FE0F 0020 0040 006D 0065 006E 0074 0069 006F 006E 17
UTF-16-encoded bytes: 3D D8 4D DC 3C D8 FF DF 0C 27 3C D8 FF DF 0F FE 20 00 40 00 6D 00 65 00 6E 00 74 00 69 00 6F 00 6E 00 34
UTF-8-encoded bytes: F0 9F 91 8D F0 9F 8F BF E2 9C 8C F0 9F 8F BF EF B8 8F 20 40 6D 65 6E 74 69 6F 6E 27
строки PHP изначально являются байтами.
strlen()
подсчитывает количество байтов в строке: 27.
mb_strlen(..., 'utf-8')
подсчитывает количество кодовых точек (символов Юникода) в строке, когда ее байты декодируются в символы с помощью кодировки UTF-8: 14.
(другие примеры подсчетов в основном бессмысленны, поскольку они основаны на обработке входной строки как одной кодировки, когда на самом деле это содержит данные в другой кодировке.)
NSStrings изначально считаются кодовыми единицами UTF-16. Есть 17, а не 14, потому что вышеуказанная строка содержит такие символы, как that don't fit in a single UTF-16 code unit, so have to be encoded as a surrogate pair. There aren't any functions that will count strings in UTF-16 code units in PHP, but because each code unit is encoded to two bytes, you can work it out easily enough by encoding to UTF-16 and dividing the number of bytes by two:
(Note: the le
суффикс необходимо сделать iconv
кодировать к определенной endianness UTF-16, и не испортить счет, выбрав один и добавив BOM в начале строки, чтобы сказать, какой из них он выбрал.)
Я включил изображение, чтобы проиллюстрировать ответ, который дал @bobince.
по сути, все номера-суррогатные пары кодовых точек в конечном итоге, как два байта в UTF-16, хотя все суррогатные пары кодовых точек в конечном итоге, как четыре байта. Если мы разделим это на два, мы получим эквивалентное ожидаемое значение длины.
P. S. пожалуйста, простите ошибку на рисунке, где написано "код точки" и должен сказать, "код единиц измерения"