emoji表情是啥就不具體介紹了,主要記住一點就是emoji是使用4字節來表示的,具體的unicode碼能夠查看這裏,因此在顯示存儲的時候就跟普通的字符大有不一樣。php
項目中原先沒有考慮到emoji表情的存在,致使問題的出現,在存儲時,使用的字符編碼集就是utf-8編碼,utf-8編碼雖然是使用1-6個變長子節表示的,可是在mysql中是使用3子節表示的,恰好沒發表示emoji表情,處理方法最簡單的固然是修改mysql的配置,utf-8改成utf-8mb4編碼,固然表的字符編碼,數據庫鏈接的編碼都須要修改,可是線上的數據庫修改比較麻煩,風險較大,這種方法應該在設計初比較適合,可是中後期不適合,pass。html
而後就是不考慮emoji表情,直接刪除掉,很簡單,直接使用正則表達式,匹配替換,在網上找了幾個代碼,都是可使用的,java
public static function remove_emoji($text){ //直接去除 return preg_replace('/([0-9|#][\x{20E3}])|[\x{00ae}|\x{00a9}|\x{203C}|\x{2047}|\x{2048}|\x{2049}|\x{3030}|\x{303D}|\x{2139}|\x{2122}|\x{3297}|\x{3299}][\x{FE00}-\x{FEFF}]?|[\x{2190}-\x{21FF}][\x{FE00}-\x{FEFF}]?|[\x{2300}-\x{23FF}][\x{FE00}-\x{FEFF}]?|[\x{2460}-\x{24FF}][\x{FE00}-\x{FEFF}]?|[\x{25A0}-\x{25FF}][\x{FE00}-\x{FEFF}]?|[\x{2600}-\x{27BF}][\x{FE00}-\x{FEFF}]?|[\x{2900}-\x{297F}][\x{FE00}-\x{FEFF}]?|[\x{2B00}-\x{2BF0}][\x{FE00}-\x{FEFF}]?|[\x{1F000}-\x{1F6FF}][\x{FE00}-\x{FEFF}]?/u', '', $text); } public static function emojiFilter($text){ //直接去除 $text = json_encode($text); preg_match_all("/(\\\\ud83c\\\\u[0-9a-f]{4})|(\\\\ud83d\\\u[0-9a-f]{4})|(\\\\u[0-9a-f]{4})/", $text, $matchs); if(!isset($matchs[0][0])) { return json_decode($text, true); } $emoji = $matchs[0]; foreach($emoji as $ec) { $hex = substr($ec, -4); if(strlen($ec)==6) { if($hex>='2600' and $hex<='27ff') { $text = str_replace($ec, '', $text); } } else { if($hex>='dc00' and $hex<='dfff') { $text = str_replace($ec, '', $text); } } } return json_decode($text, true); } public static function re($somestr){ //直接去除 $some_string = preg_replace('/[\x00-\x08\x10\x0B\x0C\x0E-\x19\x7F]'. '|[\x00-\x7F][\x80-\xBF]+'. '|([\xC0\xC1]|[\xF0-\xFF])[\x80-\xBF]*'. '|[\xC2-\xDF]((?![\x80-\xBF])|[\x80-\xBF]{2,})'. '|[\xE0-\xEF](([\x80-\xBF](?![\x80-\xBF]))|(?![\x80-\xBF]{2})|[\x80-\xBF]{3,})/S', '?', $somestr ); //reject overly long 3 byte sequences and UTF-16 surrogates and replace with ? $some_string = preg_replace('/\xE0[\x80-\x9F][\x80-\xBF]'. '|\xED[\xA0-\xBF][\x80-\xBF]/S','?', $some_string ); return $some_string; }
項目中使用的是php語言,因此找到幾個都是php的代碼,其它語言也是相似的。mysql
考慮到信息丟失等問題,能夠借鑑以上的方法,使用正則表達式,給相應的emoji表情編碼作標記,傳輸的時候再去除這些標籤,就能夠解決了。搜索了下,參考這裏,提出下面的代碼:正則表達式
public static function conver($content){ //第三方標記 $length = mb_strlen($content,'utf-8'); for ($i=0; $i < $length; $i++) { $_tmpStr = mb_substr($content,$i,1,'utf-8'); if(strlen($_tmpStr) >= 4){ $strEncode .= '[[EMOJI:'.base64_encode($_tmpStr).']]'; }else{ $strEncode .= $_tmpStr; } } return $strEncode; } public static function back($content){ ////第三方標記去除 $callback = array('Tool_Emoji', 'rawurl'); $res = preg_replace_callback("/\[\[EMOJI:(.*?)\]\]/", $callback, $content); return $res; /* $text = preg_replace_callback("/\[\[EMOJI:(.*?)\]\]/", function($matches){ return rawurldecode($matches[1]); //php版本問題,沒法直接使用 }, $content); return $text; */ } public static function rawurl($matches){ return base64_decode($matches[1]); }
這裏和參考頁不同的地方在於編碼的方式不一樣,使用base64進行編碼能夠節省空間,相應的數據行也會減少。sql
這裏也貼出java對這個問題的解決代碼,參考這裏數據庫
import java.net.URLEncoder; import java.net.URLDecoder; import java.util.regex.Matcher; import java.util.regex.Pattern; import java.io.UnsupportedEncodingException; public class test{ public static void main(String[] args) throws Exception { String content = args[0]; System.out.println(content); int strLength = content.length(); String filterContent = emojiFilter(content); System.out.println(filterContent); String emojiStr = emojiRecovery(filterContent); System.out.println(emojiStr); } private static String emojiFilter(String str){ String patternString = "([\\x{10000}-\\x{10ffff}\ud800-\udfff])"; Pattern pattern = Pattern.compile(patternString); Matcher matcher = pattern.matcher(str); StringBuffer sb = new StringBuffer(); while(matcher.find()) { try { matcher.appendReplacement(sb, "[[EMOJI:" + URLEncoder.encode(matcher.group(1),"UTF-8") + "]]"); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } } matcher.appendTail(sb); return sb.toString(); } private static String emojiRecovery(String str){ String patternString = "\\[\\[EMOJI:(.*?)\\]\\]"; Pattern pattern = Pattern.compile(patternString); Matcher matcher = pattern.matcher(str); StringBuffer sb = new StringBuffer(); while(matcher.find()) { try { matcher.appendReplacement(sb, URLDecoder.decode(matcher.group(1),"UTF-8")); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } } matcher.appendTail(sb); return sb.toString(); } }
固然,公司內部也是有處理emoji的工具的,直接把相應的emoji表情替換爲相應的圖片地址,可是考慮到emoji表情的不斷增多,工具更新的及時性,並且服務端與客戶端展現的圖片不同,這裏就不使用了。json
ps:本人工做主要是爲客戶端提供相應的接口以展現數據。app
這是很久以前的項目了,蹭着中秋假期回顧紀錄下,省得忘記。工具