Intereting Posts
В PHP, почему </ script> не показывает ошибку синтаксического анализа? Установка Composer в WAMP PHP Google+ Project, PHP не распознается access html 5 атрибут данных в php Получить идентификатор пользователя при входе пользователя в систему с использованием Username & Password Неустранимая ошибка: класс «PHPMailer» не найден Как я мог избежать использования MySQL-запроса в цикле While в PHP Как отправить запрос приложения Facebook для получения данных о принятии? Кто-нибудь имеет скрипт для создания горизонтального градиента (слева направо) с помощью PHP? Проблемы с отправкой в ​​базу данных cURL Сессия Laravel отсутствует после обновления страницы Как изменить разрешенную память выделенной памяти? Colon после объявления метода? Получить высоту и ширину изображения как целочисленные значения? Как отсортировать массив даты в php? Расположение заголовка + Размещение контента

Символы MySQL, UTF-8 и Emoji

Я работаю над iOS-приложением с бэкэндом PHP + MySQL. В приложении есть раздел чата, который должен поддерживать emoji. Мои таблицы: utf8_unicode_ci. Если я не называю «set names utf8» в своих сценариях, то на самом деле он работает – все, что вводится в базе данных, возвращается клиентам, как и должно быть.

Проблема в том, что это (если я правильно понимаю) неправильно хранит специальные символы в базе данных, и это прерывает сравнение строк (т. Е. При сравнении строк больше не совпадает с i).

Однако, если я вызываю имена наборов utf8, внезапно символы emoji вставляются как куча вопросительных знаков.

Какие-либо предложения по правильному обращению с этим? Благодаря!

Проблема заключается в том, что db имеет диакритическое нечувствительное сравнение. Другая проблема состоит из символов, • может быть выражена как один символ Юникода, либо два, образующие суррогатную пару. Существуют методы преобразования строки в предварительно сложенную или разложенную форму: precomposedStringWith * и decposedStringWith *.

Кажется, что MySQL поддерживает две формы unicode ucs2 (это более старая форма, которая была заменена utf16), которая имеет 16 бит на символ и utf8 до 3 байтов на символ. Плохая новость заключается в том, что ни одна из форм не будет поддерживать символы плоскости 1, которые требуют 17 бит. (главным образом эможи). Он похож на MySQL 5.5.3, а также поддерживает utf8mb4, utf16 и utf32 поддерживает BMP и дополнительные символы (читайте emoji). См. MySQL Unicode Character Sets .

Вот несколько кодов и результатов, чтобы продемонстрировать различные представления байтов в юникоде.
Unicode – это 21-битная система кодирования.
UTF32 непосредственно представляет собой кодовые точки и наглядно демонстрирует разложенные суррогатные пары.
UTF8 и UTF16 требуют, чтобы один или несколько байтов представляли символ юникода.

NSLog(@"character: %@", @"Å"); NSLog(@"decomposedStringWithCanonicalMapping UTF8: %@", [[@"Å" decomposedStringWithCanonicalMapping] dataUsingEncoding:NSUTF8StringEncoding]); NSLog(@"decomposedStringWithCanonicalMapping UTF16: %@", [[@"Å" decomposedStringWithCanonicalMapping] dataUsingEncoding:NSUTF16BigEndianStringEncoding]); NSLog(@"decomposedStringWithCanonicalMapping UTF32: %@", [[@"Å" decomposedStringWithCanonicalMapping] dataUsingEncoding:NSUTF32BigEndianStringEncoding]); NSLog(@"precomposedStringWithCanonicalMapping UTF8: %@", [[@"Å" precomposedStringWithCanonicalMapping] dataUsingEncoding:NSUTF8StringEncoding]); NSLog(@"precomposedStringWithCanonicalMapping UTF16: %@", [[@"Å" precomposedStringWithCanonicalMapping] dataUsingEncoding:NSUTF16BigEndianStringEncoding]); NSLog(@"precomposedStringWithCanonicalMapping UTF32: %@", [[@"Å" precomposedStringWithCanonicalMapping] dataUsingEncoding:NSUTF32BigEndianStringEncoding]); NSLog(@"character: %@", @"😱"); NSLog(@"dataUsingEncoding UTF8: %@", [@"😱" dataUsingEncoding:NSUTF8StringEncoding]); NSLog(@"dataUsingEncoding UTF16: %@", [@"😱" dataUsingEncoding:NSUTF16BigEndianStringEncoding]); NSLog(@"dataUsingEncoding UTF32: %@", [@"😱" dataUsingEncoding:NSUTF32BigEndianStringEncoding]); 

// Для некоторых суррогатных пар нет другой формы

 NSString *aReverse = [[NSString alloc] initWithBytes:"\xD8\x3C\xDD\x70\x00" length:4 encoding:NSUTF16BigEndianStringEncoding]; NSLog(@"character: %@", aReverse); NSLog(@"dataUsingEncoding UTF8: %@", [aReverse dataUsingEncoding:NSUTF8StringEncoding]); NSLog(@"dataUsingEncoding UTF16: %@", [aReverse dataUsingEncoding:NSUTF16BigEndianStringEncoding]); NSLog(@"dataUsingEncoding UTF32: %@", [aReverse dataUsingEncoding:NSUTF32BigEndianStringEncoding]); 

Выход NSLog:

 character: Å decomposedStringWithCanonicalMapping UTF8: <41cc8a> decomposedStringWithCanonicalMapping UTF16: <0041030a> decomposedStringWithCanonicalMapping UTF32: <00000041 0000030a> precomposedStringWithCanonicalMapping UTF8: <c385> precomposedStringWithCanonicalMapping UTF16: <00c5> precomposedStringWithCanonicalMapping UTF32: <000000c5> character: 😱 dataUsingEncoding UTF8: <f09f98b1> dataUsingEncoding UTF16: <d83dde31> dataUsingEncoding UTF32: <0001f631> character: 🅰 dataUsingEncoding UTF8: <f09f85b0> dataUsingEncoding UTF16: <d83cdd70> dataUsingEncoding UTF32: <0001f170>