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
这是很久以前的项目了,蹭着中秋假期回顾纪录下,省得忘记。工具