Я работаю над 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>