2014-06-17 18 views
1

我正在開發一個帶有PHP + MySQL後端的iOS應用程序。該應用程序有一個聊天部分,需要支持表情符號。 我的表格是utf8_unicode_ci。如果我不在腳本中調用'set names utf8',它實際上可以工作的表情符號 - 無論在數據庫中輸入什麼內容,都會返回給客戶端。MySQL,UTF-8和表情符號

的問題是,這(如果我理解正確的話)不正確地存儲特殊字符在數據庫中,這打破了字符串比較(即我不再同我比較字符串時)。

但是,如果我這樣做叫集名稱UTF8,突然表情符號字符插入爲一堆questionmarks的。

有關正確處理此問題的任何建議?謝謝!

回答

1

的問題是羯羊分貝具有變音不敏感的比較。另一個問題是組成字符,ï可以表示爲一個unicode字符或兩個形成代理對。有一些方法可以將字符串轉換爲預先組合或分解的形式:precomposedStringWith *和decomposedStringWith *。

看來MySQL支持兩種形式的unicode ucs2(這是一種由utf16取代的舊形式),每種字符16位,utf8每種字符最多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> 
+0

這似乎是真正有用的信息。我目前無法驗證,因爲此刻我無法升級我的MySQL,但我會認爲您是正確的並接受您的答案:)謝謝! – SvenM

+0

如果您不介意,我還有一個問題。如果我不需要像我描述的字符串匹配,是否有任何其他缺點不調用集名稱utf8?我知道數據插入不正確,但它在客戶端顯示數據時起作用。 – SvenM

+0

不幸的是,我對「集合名稱utf8」一無所知,自從我編寫與MySQL一起工作的代碼以來,這已經有好幾年了。請使用Plane 1代碼點進行測試(表情符號位於Plane 1中)。也代理對,但他們可能只是比較問題。我在回答中添加了一些代碼和結果以演示不同的Unicode字節表示。 – zaph