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. пожалуйста, простите ошибку на рисунке, где написано "код точки" и должен сказать, "код единиц измерения"

unicode breakdown