记录下emoji的处理

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

这是很久以前的项目了,蹭着中秋假期回顾纪录下,省得忘记。工具

相关文章
相关标签/搜索