記錄下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

這是很久以前的項目了,蹭着中秋假期回顧紀錄下,省得忘記。工具

相關文章
相關標籤/搜索