6-байтовые эмоджи из NSUTF8StringEncoding - PullRequest
2 голосов
/ 20 марта 2020

Меня смущает представление байтов смайликов, закодированных в UTF8. Насколько я понимаю, символы UTF8 имеют переменный размер, до 4 байтов.

Когда я кодирую ❤️ emoji в UTF8 на iOS 13, я получаю обратно 6 байтов:

NSString* heartEmoji = @"❤️";
NSData* utf8 = [heartEmoji dataUsingEncoding:NSUTF8StringEncoding];
NSLog(@"%@", utf8); // {length = 6, bytes = 0xe29da4efb88f}

Если я вернусь к операции, просто потребляя первые 3 байта, я получу сердце в юникоде:

BYTE bytes[3] = { 0 };
[utf8 getBytes:bytes length:3];
NSString* decoded = [[NSString alloc] initWithBytes:bytes length:3 encoding:NSUTF8StringEncoding];
NSLog(@"%@", decoded); // ❤

Обратите внимание, что я использую сердце в качестве примера; Я пробовал много эмодзи, и большинство из них имеют 4 байта в UTF8, но некоторые имеют размер 6.

Есть ли у меня ошибочные предположения относительно UTF8? Что я могу сделать, чтобы представить все смайлики в 4 байта как UTF8?

1 Ответ

2 голосов
/ 20 марта 2020

Насколько я понимаю, символы UTF8 имеют переменный размер, до 4 байтов.

Это не совсем правильно. UTF8 кодовая точка - до 4 байтов. Но персонаж (в частности, расширенный кластер графем) может быть намного длиннее из-за объединения символов. Минимум десятки байтов, а в самых крайних случаях неограничен. См. Почему символы эмодзи, такие как ?‍?‍?‍?, так странно трактуются в строках Swift? для интересного примера.

В вашем примере, ваши эмодзи - HEAVY BACK HEART (U + 2764), за которым следует VARIATION SELECTOR-16 (U + FE0F), который указывает, что он должен быть красного цвета. UTF-8 требует три байта для кодирования каждой из этих кодовых точек.

...