MySQL,UTF-8和Emoji字符

时间:2014-06-17 00:11:21

标签: php mysql ios utf-8 emoji

我正在开发一个带有PHP + MySQL后端的iOS应用程序。该应用有一个聊天部分,需要支持表情符号。 我的表是utf8_unicode_ci。如果我不在我的脚本中调用'set names utf8',那么表情符号它实际上是可行的 - 无论在数据库中输入什么,都会按原样返回给客户端。

问题在于(如果我理解正确的话)在数据库中错误地存储了特殊字符,这会破坏字符串比较(即ï在比较字符串时不再与i相同)。

但是,如果我调用集合名称utf8,那么表情符号字符会突然插入一堆问号。

有关正确处理方法的任何建议吗?谢谢!

1 个答案:

答案 0 :(得分:1)

问题是db有一个变量不敏感的比较。另一个问题是组成字符,ï可以表示为一个unicode字符或两个形成代理对。有一些方法可以将字符串转换为预先组合或分解的形式:precomposedStringWith *和decomposedStringWith *。

似乎MySQL支持两种形式的unicode ucs2(这是一种由utf16取代的旧形式),每个字符为16位,每个字符最多为3个字节。坏消息是,这两种形式都不支持需要17位的平面1字符。 (主要是表情符号)。它看起来像MySQL 5.5.3及更高版本也支持utf8mb4,utf16和utf32支持BMP和补充字符(读表情符号)。请参阅MySQL Unicode Character Sets

以下是一些代码和结果,用于演示不同的unicode字节表示 Unicode是一个21位编码系统 UTF32直接代表代码点并清楚地展示分解的代理对 UTF8和UTF16需要一个或多个字节来表示unicode字符。

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>