<h3>先補習一下Unicode 與 UTF-8的歷史演變過程</h3>
http://www.lxweimin.com/p/ab0dcfb9bb74
以下內容轉自文章:
http://blog.csdn.net/ugg/article/details/44225723
http://blog.csdn.net/tge7618291/article/details/7599902
emoji資料
今天研究了emoji,挺有意思,資料挺多,摘要一些信息給大家分享,也算是自己記錄學習。
emoji介紹
Emoji (絵文字,詞義來自日語えもじ,e-moji,moji在日語中的含義是字符)是一套起源于日本的12x12像素表情符號,由栗田穣崇(Shigetaka Kurit)創作,最早在日本網絡及手機用戶中流行,自蘋果公司發布的iOS 5輸入法中加入了emoji后,這種表情符號開始席卷全球,目前emoji已被大多數現代計算機系統所兼容的Unicode編碼采納,普遍應用于各種手機短信和社交網絡中。近期,更是有不少網友用emoji圖案玩猜字游戲,享受這種表情文化帶來的樂趣。
關于emoji的發音:很多人第一眼見到emoji便會下意識將其誤讀作“一磨嘰”,其實不然,emoji音譯過來大概讀作“誒磨嘰”,當中“e”的發音頗似字母abc的a的發音。
最初日本的三大電信運營商各自有不同的字符定義,分別是DoCoMo、KDDI和Softbank。隨著iOS內置了Softbank的版本,emoji在全球范圍內風靡(iOS5版本以前)。而Google又自己定義了一套emoji字符。iOS5以后,apple采用了unicode定義的emoji字符(iOS5版本以后)。
unicode定義的emoji是四個字符,softbank為3個字符,emoji的四個字符從存儲到展示對應沒有做過考慮的系統來說,簡直就是災難。
面臨問題:
插入Emoji表情,保存到數據庫時報錯:
SQLException: Incorrect string value: '\xF0\x9F\x98\x84' for column 'review' at row 1
UTF-8編碼有可能是兩個、三個、四個字節。Emoji表情是4個字節,而MySQL的utf8編碼最多3個字節,所以數據插不進去。
解決方案:過濾解決
把emoji直接過濾掉,簡單方便有效。雖然損失了幾個emoji字符,但強過不至于導致整條記錄丟失。
[php] view plain copy 在CODE上查看代碼片派生到我的代碼片
public static String removeNonBmpUnicode(String str) {
if (str == null) {
return null;
}
str = str.replaceAll("[^\u0000-\uFFFF]", "");
return str;
}
這種方案能預防能解決問題,并且還能是程序更加健壯,但是從用戶體驗上來說并不好,用戶發的emoji表情丟了,看下面的解決方案。
解決方案:將Mysql的編碼從utf8轉換成utf8mb4。
從 MySQL 5.5.3 開始,MySQL 支持一種 utf8mb4 的字符集,這個字符集能夠支持 4 字節的 UTF8 編碼的字符。 utf8mb4 字符集能夠完美地向下兼容 utf8 字符串。在數據存儲方面,當一個普通中文字符存入數據庫時仍然占用 3 個字節,在存入一個 Unified Emoji 表情的時候,它會自動占用 4 個字節。所以在輸入輸出時都不會存在亂碼的問題了。
要使用 MySQL 的這個特性,首先需要把 MySQL 升級到 5.5.3 以上的版本。
其次,需要修改數據結構中的字符集為 utf8mb4 ,如 utf8mb4_general_ci 。由于 utf8mb4 是 utf8 的超集,從 utf8 升級到 utf8mb4 不會有任何問題,直接升級即可;如果從別的字符集如 gb2312 或者 gbk 轉化而來,一定要先備份數據庫。
然后,修改 MySQL 的配置文件 /etc/my.cnf,修改連接默認字符集為 utf8mb4 ,如果是自己寫的 PHP 腳本,也可以在連接數據庫以后首先執行一句 SQL: SET NAMES utf8mb4;。這時候,PHP 應該就可以正常保存 Emoji 到數據庫了。
這種方式可能帶來的問題:
存儲:在數據表中,對于變長的字段(如VARCHAR2,TEXT),utf8mb4最大可存儲的字符可能少于utf8系列的collation;在索引中,對于文本類型的字段,utf8mb4可索引的字符少于utf8系列的collations。如InnoDB的索引最多使用767字節。如果使用utf8mb4,每一個字符都會預留4字節做索引,而utf8則預留3字節。故此前者是191個字符,后者是255個字符。。
性能:由于以上原因,加上字符集大,utf8mb4的性能可能比utf8系列的collations低,可以參考stackoverfolow上的一個測試結果:http://stackoverflow.com/questions/766809/whats-the-difference-between-utf8-general-ci-and-utf8-unicode-ci,差異不是特別大。
運維:如果一個大的環境內,如果其他的數據庫都是utf8模式,把其中某個庫設置為utf8mb4模式,在后續交接運維可能會造成問題,遺留下坑。
上下游:數據庫支持unicode的emoji存儲,上下游不一定支持。比如mysql客戶端驅動(低版本的jdbc就不行)可能不支持utf8mb4,或者DDL的中間件不支持utf8mb4。web端處理utf8mb4字符展示,這些都有可能影響emoji的存儲活著展示。
從上面的信息,從數據庫層面如果不是特別看重存儲,性能,運維并能解決上下游的問題,數據庫是完全可以支持emoji的,但是有個新問題沒有解決,emoji在iOS上展示OK,andriod設備如何展示emoji表情?
解決方案:轉義解決
1:unicode emoji轉softbank的emoji。
我們知道unicode emoji是4個字節,softbank定義的emoji占用3個字節存儲,通過emoji for php http://code.iamcal.com/php/emoji/,我們可以把unicode的emoji方式轉換為softbank方式,從而實現不修改數據庫,就能存儲emoji,相對于數據庫層面的解決問題的方式,動作要小的多,并且也不會有性能,運維等方面的問題。但是有個不可避免的問題是,Softbank方式已經不再維護,所以新增加的emoji表情,Softbank中都沒有,會造成部分emoji表情丟失的情況。
2:ubb
UBB代碼是HTML(標準通用標記語言下的一個應用)的一個變種,是Ultimate Bulletin Board (國外的一個BBS程序)采用的一種特殊的TAG。您也許已經對它很熟悉了。UBB代碼很簡單,功能很少,但是由于其Tag語法檢查實現非常容易,所以不少網站引入了這種代碼,以方便網友使用顯示圖片/鏈接/加粗字體等常見功能。
比如emoji的太陽符號,他的unicode emoji編碼為U+2600,在存入數據庫時,可以把它轉換成 UBB 代碼 [emoji]2600[/emoji] 保存,讀取的時候,可以轉換回來。當然針對不同的設備,比如andriod我們可以轉義成andriod可以處理的emoji符號。
這種轉移,可以很好解決iOS和Andriod顯示emoji的問題,但是還存在幾個問題。
1:andriod和iOS的emoji并不相同,相同的編碼 可能在iOS上是太陽,而在andriod上是陰天,解決這種問題方式最好做下iOS和andriod下的emoji映射,同時可以在web上通過js轉義處理。
2:性能,采用轉義的方式處理,性能肯定會有所下降,但是可以容忍。
與UBB對應的是html轉義,這種方式,其實和ubb有些類似, 使用 HTML轉義字符 ?,結果和性能和UBB差不多,從規范化上來說,ubb方式更好一些。
參考資料
PHP-emoji轉換表:http://code.iamcal.com/php/emoji/
unicode Emoji Symbols: http://www.unicode.org/~scherer/emoji4unicode/20091221/utc.html
emoji圖標和unicode對應關系:http://www.easyapns.com/iphone-emoji-alerts
談談Unicode編碼,簡要解釋UCS、UTF、BMP、BOM等名詞:http://www.fmddlmyy.cn/text6.html
emoji在線轉換工具:http://unicodey.com/js-emoji/demo.htm
Emoji表情圖標在iOS與PHP之間通信及MySQL存儲:http://blog.csdn.NET/wildfireli/article/details/9370161
Mysql中校對集utf8_unicode_ci與utf8_general_ci的區別:http://hi.baidu.com/phpkoo/item/38238bd8505899e955347fca,http://stackoverflow.com/questions/766809/whats-the-difference-between-utf8-general-ci-and-utf8-unicode-ci
Mysql排序規則utf8_unicode_ci與utf8_general_ci的區別:http://justdo2008.iteye.com/blog/2162842
Unicode Character Sets:http://dev.mysql.com/doc/refman/5.0/en/charset-unicode-sets.html
MySQL設置utf8mb4編碼:http://www.linuxidc.com/Linux/2014-07/104231.htm|
andriod支持emoji解決方案:http://blog.csdn.net/waylife/article/details/11095113
Supporting New Emojis on iOS 6:http://blog.manbolo.com/2012/10/29/supporting-new-emojis-on-ios-6
讓MySql支持Emoji表情(MySQL中4字節utf8字符保存方法):http://www.w2bc.com/Article/8533
如何處理emoji等4字節的Unicode字符:http://zhidao.baidu.com/link?url=z6PW1ya6plRBgFN7M2zdVLXUnmxYcH2_VYK8nW9Yi9-kh2estgmJomw1LssmsA853WYHsRtulkJn2okq0a3TAUDQHIiMe7b0VS-FeGMNYUu
suppoting new emoji for ios6:http://blog.manbolo.com/2012/10/29/supporting-new-emojis-on-ios-6
UTF-8格式emoji:http://punchdrunker.github.io/iOSEmoji/table_html/ios6/index.html