Java emoji持久化mysql

  很久沒有更新博客了,今天和你們分享一個關於emoji表情持久化問題,相信作web開發的都遇到過這樣的問題,由於咱們知道mysql的utf-8字符集保存不了保存不了表情字符,這是爲何呢?由於普通的字符串或者表情都是佔位3個字節,因此utf8足夠用了,可是移動端的表情符號佔位是4個字節,普通的utf8就不夠用了,爲了應對無線互聯網的機遇和挑戰、避免 emoji 表情符號帶來的問題、涉及無線相關的 MySQL 數據庫建議都提早採用 utf8mb4 字符集,這必需要做爲移動互聯網行業的一個技術選型的要點。java

  好了看到上面的結果你是否是已經去修改數據庫字符集了,若是你是我的項目或小項目上面的方法卻是一個解決方法,可是對於一個目前正在服務5000W用戶的系統,上面的方式就有點不合適了,針對這種狀況我這邊總結了三種處理方式,下面分享給你們:mysql

  一、既然是因爲移動端的表情符號佔位是4個字節,那咱們直接把數據轉換後保存。git

1.URLEncoder.encode(String s, String enc) 
使用指定的編碼機制將字符串轉換爲 application/x-www-form-urlencoded 格式 

URLDecoder.decode(String s, String enc) 
使用指定的編碼機制對 application/x-www-form-urlencoded 字符串解碼。 

  二、方法一的處理太粗躁,有沒有更好的解決辦法呢?使用輕量級工具emoji-java處理emoji表情字符github

github地址:https://github.com/vdurmont/emoji-java

  具體使用方式,你們能夠進入git中自行查看。web

  三、有了上面兩種方式,你是否是已經知足了,最爲本身最推崇的emoji處理方式,下面纔是重點,首先說一下上面兩種方式存在的問題:第一種方式,數據通過轉換,至關於加密,咱們將沒法直接查看到數據的原始內容,由其對於須要進行搜索的業務場景,將是一件很困難的事情;第二種方式,雖然避免了第一種方式存在的問題,可是它基於表情的對照表進行匹配轉換的,也就意味着對於一些新表情,沒法作到轉換,這就會致使咱們數據插入繼續出現問題,這是它第一個問題,第二點在於它將表情轉化爲對應的匹配規則,說白一點就是轉化爲英文描述,就是這個轉化,本來4個字節的表情,它可能給你轉成了10個字節甚至更多。好了說了這麼多下面咱們看一下我最後的終極解決方法:sql

/**
 * @Author: gaoshang
 * @Description:
 * @Date: 2019/7/19
 */
public class EmojiUtil {

    /**
     * 將文本中的表情轉爲十六進制
     * <p>
     *
     * @param input
     * @return
     */
    public static String parseFromAliases(String input) {
        if (input == null) {
            return input;
        }

        return stringToUnicode(input);
    }

    /**
     * 將文本中的十六進制轉爲表情
     * <p>
     *
     * @param input
     * @return
     */
    public static String parseToAliases(String input) {
        if (input == null) {
            return input;
        }

        return unicodeToString(input);
    }

    /**
     * 字符串轉unicode
     *
     * @param str
     * @return
     */
    public static String stringToUnicode(String str) {
        StringBuilder sb = new StringBuilder();
        StringBuilder cacheSB = new StringBuilder();
        char[] c = str.toCharArray();
        for (int i = 0; i < c.length; i++) {
            if (!isEmojiCharacter(c[i])) {
                if (cacheSB.length() > 0) {
                    sb.append("\\u").append(cacheSB);
                    cacheSB.delete(0, cacheSB.length());
                }

                sb.append("\\u").append("[").append(Integer.toHexString(c[i])).append("]");
            } else {
                if (c[i] == '[' || c[i] == '\\' || c[i] == ']') {
                    if (cacheSB.length() > 0) {
                        sb.append("\\u").append(cacheSB);
                        cacheSB.delete(0, cacheSB.length());
                    }
                    sb.append("\\u").append(c[i]);
                } else {
                    cacheSB.append(c[i]);
                }
            }
        }
        if (cacheSB.length() > 0) {
            if (sb.length() > 0) {
                sb.append("\\u");
            }
            sb.append(cacheSB);
        }
        return sb.toString();
    }

    /**
     * unicode轉字符串
     *
     * @param unicode
     * @return
     */
    public static String unicodeToString(String unicode) {
        StringBuilder sb = new StringBuilder();
        String[] hex = unicode.split("\\\\u");
        for (int i = 0; i < hex.length; i++) {
            if (hex[i].indexOf("[") == 0 && hex[i].indexOf("]") == hex[i].length() - 1) {
                try {
                    int index = Integer.parseInt(hex[i].substring(1, hex[i].length() - 1), 16);
                    sb.append((char) index);
                } catch (NumberFormatException e) {
                    sb.append(hex[i]);
                }
            } else {
                sb.append(hex[i]);
            }
        }
        return sb.toString();
    }

    private static boolean isEmojiCharacter(char codePoint) {
        return (codePoint == 0x0) || (codePoint == 0x9) || (codePoint == 0xA)
                || (codePoint == 0xD)
                || ((codePoint >= 0x20) && (codePoint <= 0xD7FF))
                || ((codePoint >= 0xE000) && (codePoint <= 0xFFFD))
                || ((codePoint >= 0x10000) && (codePoint <= 0x10FFFF));
    }

}

  好了就先這樣,歡迎你們提出不一樣的見解,已經好的解決方案。數據庫

相關文章
相關標籤/搜索