天天看點

APP後端處理表情的一些技巧 1.表情在mysql的存儲 2.當文字中夾帶表情的處理 3.openfire中發送表情引起斷開連接配接的問題

app應用中文字夾帶表情是個很常見的現象。甚至一些40多歲的大叔級使用者,也喜歡在自己的昵稱中夾帶表情,在産品營運後發現這個現象,徹底颠覆了我的世界觀。

在背景處理表情的時間,我遇到過下面3個問題:

         表情的utf8編碼,有時是有4個位元組的,是以在一般的utf編碼是沒法存儲的。

在網上看到一個常用的解決方案,是把mysql更新到5.5,然後把字元編碼改為utf8mb4_general_ci。

但實際情況是,有可能在以前的app版本中不需要支援表情,這時系統已經營運了一段時間了,這時才把mysql更新并遷移資料,需要很高的運維成本,同時具備一定的風險,例如,遷移前的不同mysql版本間需要資料同步,保證資料的一緻性;遷移過程中可能出現意想不到的事情,造成服務停止。

但在實踐中,我發現了還有一個方法,适用于mysql 5.1,就是把含有表情的那個字段的類型變為blob, 沒錯,就是用二進制存儲,這樣就能比較少的改動mysql。

   很多時候,如果文字中夾帶表情,那麼這些文字的處理就會出現問題,例如,如果一個使用者的昵稱帶有表情,那麼我怎麼把這個昵稱轉換為拼音呢?在推送apns過程中,如果推送的文字中夾帶表情,推送到app端後也會顯示亂碼。

在app後端,存在着大量要處理文字中夾帶表情的需求。我遇到了這個問題,先是找到了 https://github.com/iamcal/php-emoji這個轉換表情的類庫,但發現這個類庫不支援ios6後新增的表情,最後沒辦法了,我寫了個抓取程式,把 http://punchdrunker.github.io/iOSEmoji/table_html/ios6/index.html中ios6後新增的表情抓取出來,并寫了個新的類庫并開源了 https://github.com/newjueqi/converemojitostr,這個類庫的作用就是把文字中夾帶的表情替換為一個特殊的字元(預設是"#")。

openfire中,如果發送某些特殊的字元(例如一些表情符合),會斷開xmpp的連接配接,經查,是由以下的代碼問題引起的:

src\java\org\jivesoftware\openfire\net\MXParser.java

protected char more() throws IOException, XmlPullParserException {  

        final char codePoint  = super.more(); // note - this does NOT return a codepoint now, but simply a (single byte) character!  

        if ((codePoint == 0x0) ||  // 0x0 is not allowed, but flash clients insist on sending this as the very first character of a stream. We should stop allowing this codepoint after the first byte has been parsed.  

                (codePoint == 0x9) ||                              

                (codePoint == 0xA) ||  

                (codePoint == 0xD) ||  

                ((codePoint >= 0x20) && (codePoint <= 0xD7FF)) ||  

                ((codePoint >= 0xE000) && (codePoint <= 0xFFFD)) ||  

                ((codePoint >= 0x10000) && (codePoint <= 0x10FFFF))) {  

            return codePoint;  

        }  

        throw new XmlPullParserException("Illegal XML character: " + Integer.parseInt(codePoint+"", 16));  

    }  

由于在這裡把特殊的字元當成了一個異常,是以openfire會斷開連接配接。

解決方法:

@Override  

   protected char more() throws IOException, XmlPullParserException {  

    final char codePoint  = super.more(); // note - this does NOT return a codepoint now, but simply a (single byte) character!  

    if ((codePoint == 0x0) ||  // 0x0 is not allowed, but flash clients insist on sending this as the very first character of a stream. We should stop allowing this codepoint after the first byte has been parsed.  

            (codePoint == 0x9) ||                              

            (codePoint == 0xA) ||  

            (codePoint == 0xD) ||         

            //fix some emotion  

            ((codePoint >= 0x20) && (codePoint <= 0xFFFD)) ||               

            ((codePoint >= 0x10000) && (codePoint <= 0x10FFFF))) {  

        return codePoint;  

    throw new XmlPullParserException("Illegal XML character: " + Integer.parseInt(codePoint+"", 16));  

   }      

如何聯系我:【萬裡虎】www.bravetiger.cn

【QQ】3396726884 (咨詢問題100元起,幫助解決問題500元起)

【部落格】http://www.cnblogs.com/kenshinobiy/