如何轉義emoji表情,讓它可以存入utf8的資料庫?

來源:互聯網
上載者:User

unicode emoji是4個位元組的,存不進MySQL裡,找到一個轉義的庫http://code.iamcal.com/php/emoji/,但是轉為Unicode之後,還是4個位元組,一樣存不進,應該說根本沒轉。轉為其他格式的emoji又怕以後新增了表情不好做,你們在不改資料庫編碼的前提下,是怎麼弄的?

方法1:base_encode64

這種方法是可以,但是舊資料沒有經過encode操作,取資料的時候如果統一進行decode的話,舊資料會丟失的。

方法2:urlencode

這個似乎可以,對沒有經過encode的資料進行decode也不會有影響,而且多次decode似乎也不會有影響。你們說這個方法有缺陷嗎?

=======================
一個發現,擷取使用者基本資料的時候,笑哭那個表情print_r出的是\ud83d\ude02,而我儲存的時候,報錯說這個 \xF0\x9F\x98\x82 值不能儲存,請問這是怎麼回事,自動轉碼了,轉成的這是什嗎?是轉碼過了嗎?

=======================

方法3:最後採用了下面採納的那個方法,因為我覺得它有下面幾個優點:

1、那個方法只轉換表情,不會轉換中文,所以資料還是直接可讀的
資料庫中儲存起來是這樣的, 後面的\ud83d\udca5可以隨意複製粘貼,而顯示出來是這樣的,

2、不會把表情轉換為其它標準,只有一個簡單的,固定的轉換演算法,也就是說不需要一個表情庫來對照著轉換,所以以後其它人要使用這個資料的時候,也很容易知道每個表情是對應的哪個。就算蘋果大爺又增加了表情,也不需要做什麼額外的修改。

3、可以無限decode輸出的都是正確的內容。因為有的時候可能需要在一次請求中的兩個地方做decode,其它decode多次會把正確的資料改成其它資料,這個不會。

缺點:
1、看了下面的代碼就知道,這個是強制修改字元編碼中,指定區間內的編碼,也就說有可能誤殺,也有可能有超出這個區間的emoji沒殺到。不過僅僅是在字元前加反斜線,即使誤殺了,發現之後也很容易改回來。
資料庫中發現有這樣的 ,是漏殺了,但是不知道為什麼,這個可以直接存資料庫。

/**  把使用者輸入的文本轉義(主要針對特殊符號和emoji表情) */function userTextEncode($str){    if(!is_string($str))return $str;    if(!$str || $str=='undefined')return '';    $text = json_encode($str); //暴露出unicode    $text = preg_replace_callback("/(\\\u[ed][0-9a-f]{3})/i",function($str){        return addslashes($str[0]);    },$text); //將emoji的unicode留下,其他不動,這裡的正則比原答案增加了d,因為我發現我很多emoji實際上是\ud開頭的,反而暫時沒發現有\ue開頭。    return json_decode($text);}/**  解碼上面的轉義 */function userTextDecode($str){    $text = json_encode($str); //暴露出unicode    $text = preg_replace_callback('/\\\\\\\\/i',function($str){        return '\\';    },$text); //將兩條斜杠變成一條,其他不動    return json_decode($text);}

回複內容:

unicode emoji是4個位元組的,存不進MySQL裡,找到一個轉義的庫http://code.iamcal.com/php/emoji/,但是轉為Unicode之後,還是4個位元組,一樣存不進,應該說根本沒轉。轉為其他格式的emoji又怕以後新增了表情不好做,你們在不改資料庫編碼的前提下,是怎麼弄的?

方法1:base_encode64

這種方法是可以,但是舊資料沒有經過encode操作,取資料的時候如果統一進行decode的話,舊資料會丟失的。

方法2:urlencode

這個似乎可以,對沒有經過encode的資料進行decode也不會有影響,而且多次decode似乎也不會有影響。你們說這個方法有缺陷嗎?

=======================
一個發現,擷取使用者基本資料的時候,笑哭那個表情print_r出的是\ud83d\ude02,而我儲存的時候,報錯說這個 \xF0\x9F\x98\x82 值不能儲存,請問這是怎麼回事,自動轉碼了,轉成的這是什嗎?是轉碼過了嗎?

=======================

方法3:最後採用了下面採納的那個方法,因為我覺得它有下面幾個優點:

1、那個方法只轉換表情,不會轉換中文,所以資料還是直接可讀的
資料庫中儲存起來是這樣的, 後面的\ud83d\udca5可以隨意複製粘貼,而顯示出來是這樣的,

2、不會把表情轉換為其它標準,只有一個簡單的,固定的轉換演算法,也就是說不需要一個表情庫來對照著轉換,所以以後其它人要使用這個資料的時候,也很容易知道每個表情是對應的哪個。就算蘋果大爺又增加了表情,也不需要做什麼額外的修改。

3、可以無限decode輸出的都是正確的內容。因為有的時候可能需要在一次請求中的兩個地方做decode,其它decode多次會把正確的資料改成其它資料,這個不會。

缺點:
1、看了下面的代碼就知道,這個是強制修改字元編碼中,指定區間內的編碼,也就說有可能誤殺,也有可能有超出這個區間的emoji沒殺到。不過僅僅是在字元前加反斜線,即使誤殺了,發現之後也很容易改回來。
資料庫中發現有這樣的 ,是漏殺了,但是不知道為什麼,這個可以直接存資料庫。

/**  把使用者輸入的文本轉義(主要針對特殊符號和emoji表情) */function userTextEncode($str){    if(!is_string($str))return $str;    if(!$str || $str=='undefined')return '';    $text = json_encode($str); //暴露出unicode    $text = preg_replace_callback("/(\\\u[ed][0-9a-f]{3})/i",function($str){        return addslashes($str[0]);    },$text); //將emoji的unicode留下,其他不動,這裡的正則比原答案增加了d,因為我發現我很多emoji實際上是\ud開頭的,反而暫時沒發現有\ue開頭。    return json_decode($text);}/**  解碼上面的轉義 */function userTextDecode($str){    $text = json_encode($str); //暴露出unicode    $text = preg_replace_callback('/\\\\\\\\/i',function($str){        return '\\';    },$text); //將兩條斜杠變成一條,其他不動    return json_decode($text);}

我是這麼玩兒的

給一個標準的解決方案:

  1. mysql的版本必須為v5.5.3或更高

  2. 把資料庫的編碼改成utf8mb4 -- UTF-8 Unicode

  3. 然後需要儲存emoji表情的欄位選擇utf8mb4_general_ci

  4. 資料庫連接也需要改為utf8mb4

設定完成後,應該可以看到如下類似字元集設定結果。那麼可以直接的存入資料庫,無需做任何額外的事情了。

mysql> SHOW VARIABLES WHERE Variable_name LIKE 'character\_set\_%' OR Variable_name LIKE 'collation%';  +--------------------------+--------------------+  | Variable_name            | Value              |  +--------------------------+--------------------+  | character_set_client     | utf8mb4            |  | character_set_connection | utf8mb4            |  | character_set_database   | utf8mb4            |  | character_set_filesystem | binary             |  | character_set_results    | utf8mb4            |  | character_set_server     | utf8mb4            |  | character_set_system     | utf8               |  | collation_connection     | utf8mb4_unicode_ci |  | collation_database       | utf8mb4_unicode_ci |  | collation_server         | utf8mb4_unicode_ci |  +--------------------------+--------------------+   rows in set (0.00 sec) 

我在做公眾平台開發時遇到過這個問題,使用者的暱稱可以包含表情(坑爹- -!)。於是我就將整個暱稱轉換成HEX字串存在MySQL中,目前使用者1W+,系統穩定,題主可以參考一下此方案。

MySQL支援hex() and unhex()函數。Java可以使用org.apache.commons.codec.binary.Hex工具類。其他語言也有相應的方法。

試試微博或qq裡面的那種方式?用簡單的編碼來映射,比如微笑可以用 [wx]/wx 。不過表情多了之後4個字元不怎麼夠用。。。

urldecode
我看了一下 decode 的源碼,應該是不會出現問題。

只要沒有 % 解碼後肯定還是原來的字元(串),有 % 會出現兩種情況,一種是解碼成功,這個時候肯定就不是原來的字串了,一種是解碼失敗,拋出異常(其實這個異常可以作為是否 encode的標準)。

解碼還算是比較嚴格吧,作為使用者名稱的情況下 出現 % 還解碼成功的機率比較小吧,對於這部分你可以手動改資料庫,應該不會有很多。

你試試這個函數,之前弄自訂菜單的時候,也接觸過Emoji表情,當時看到用的這個函數把Emoji表情的編碼給轉換了。

function utf8_bytes($cp) {    if ($cp > 0x10000){        # 4 bytes        return    chr(0xF0 | (($cp & 0x1C0000) >> 18)).        chr(0x80 | (($cp & 0x3F000) >> 12)).        chr(0x80 | (($cp & 0xFC0) >> 6)).        chr(0x80 | ($cp & 0x3F));    }else if ($cp > 0x800){        # 3 bytes        return    chr(0xE0 | (($cp & 0xF000) >> 12)).        chr(0x80 | (($cp & 0xFC0) >> 6)).        chr(0x80 | ($cp & 0x3F));    }else if ($cp > 0x80){        # 2 bytes        return    chr(0xC0 | (($cp & 0x7C0) >> 6)).        chr(0x80 | ($cp & 0x3F));    }else{        # 1 byte        return chr($cp);    }}

  1. 使用BOLO類型

  2. 將資料庫編碼改為 utf8mb4

我這個剛解決的這個問題(後端是java實現的,資料庫Mysql),供參考。
1、修改儲存emoji欄位編碼,例如放在username欄位中:

    ALTER TABLE user CHANGE username username VARCHAR(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci default null;

2、java在執行資料庫插入、更新操作前,要先執行 sql語句"set names utf8mb4" 語句。

https://github.com/iamcal/php-emoji
我是用這個處理的~

http://www.emoji-cheat-sheet.com/

有一種編碼叫 utfmb4,支援 4 位長度的 utf8 編碼

喏,你的 MySQL 版本必須為 5.5 以上的

不用轉,直接資料庫轉成utf8mb4, 我以前就是這麼乾的

不用更改整個資料庫的把。。。create xxx() charset=utf8mb4 單表 utf8mb4就行了把

因為我的項目中需要對字數有限制的需求,涉及到逐字計數,在這基礎上我增加了emoji的功能完美實現。你需要代碼的話請再告訴我,我提供給你。

  • 相關文章

    聯繫我們

    該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

    如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

    A Free Trial That Lets You Build Big!

    Start building with 50+ products and up to 12 months usage for Elastic Compute Service

    • Sales Support

      1 on 1 presale consultation

    • After-Sales Support

      24/7 Technical Support 6 Free Tickets per Quarter Faster Response

    • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.