记录下emoji的处理

拟墨画扇 提交于 2019-12-03 10:02:05

emoji表情是啥就不具体介绍了,主要记住一点就是emoji是使用4字节来表示的,具体的unicode码可以查看这里,所以在显示存储的时候就跟普通的字符大有不同。

项目中原先没有考虑到emoji表情的存在,导致问题的出现,在存储时,使用的字符编码集就是utf-8编码,utf-8编码虽然是使用1-6个变长子节表示的,但是在mysql中是使用3子节表示的,刚好没发表示emoji表情,处理方法最简单的当然是修改mysql的配置,utf-8改为utf-8mb4编码,当然表的字符编码,数据库连接的编码都需要修改,但是线上的数据库修改比较麻烦,风险较大,这种方法应该在设计初比较适合,但是中后期不适合,pass。

然后就是不考虑emoji表情,直接删除掉,很简单,直接使用正则表达式,匹配替换,在网上找了几个代码,都是可以使用的,

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的代码,其它语言也是类似的。

考虑到信息丢失等问题,可以借鉴以上的方法,使用正则表达式,给相应的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进行编码可以节省空间,相应的数据行也会减小。

这里也贴出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表情的不断增多,工具更新的及时性,而且服务端与客户端展示的图片不一样,这里就不使用了。

ps:本人工作主要是为客户端提供相应的接口以展示数据。

这是好久之前的项目了,蹭着中秋假期回顾纪录下,免得忘记。

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!