开发者社区> 优惠码优惠> 正文

Java emoji持久化mysql

简介: Java emoji持久化mysql  好久没有更新博客了,今天和大家分享一个关于emoji表情持久化问题,相信做web开发的都遇到过这样的问题,因为我们知道mysql的utf-8字符集保存不了保存不了表情字符,这是为什么呢?因为普通的字符串或者表情都是占位3个字节,所以utf8足够用了,但是移动端的表情符号占位是4个字节,普通的utf8就不够用了,为了应对无线互联网的机遇和挑战、避免 emoji 表情符号带来的问题、涉及无线相关的 MySQL 数据库建议都提前采用 utf8mb4 字符集,这必须要作为移动互联网行业的一个技术选型的要点。
+关注继续查看

Java emoji持久化mysql
  好久没有更新博客了,今天和大家分享一个关于emoji表情持久化问题,相信做web开发的都遇到过这样的问题,因为我们知道mysql的utf-8字符集保存不了保存不了表情字符,这是为什么呢?因为普通的字符串或者表情都是占位3个字节,所以utf8足够用了,但是移动端的表情符号占位是4个字节,普通的utf8就不够用了,为了应对无线互联网的机遇和挑战、避免 emoji 表情符号带来的问题、涉及无线相关的 MySQL 数据库建议都提前采用 utf8mb4 字符集,这必须要作为移动互联网行业的一个技术选型的要点。

  好了看到上面的结果你是不是已经去修改数据库字符集了,如果你是个人项目或小项目上面的方法倒是一个解决方法,但是对于一个目前正在服务5000W用户的系统,上面的方式就有点不合适了,针对这种情况我这边总结了三种处理方式,下面分享给大家:

  1、既然是由于移动端的表情符号占位是4个字节,那我们直接把数据转换后保存。

1.URLEncoder.encode(String s, String enc)
使用指定的编码机制将字符串转换为 application/x-www-form-urlencoded 格式

URLDecoder.decode(String s, String enc)
使用指定的编码机制对 application/x-www-form-urlencoded 字符串解码。
  2、方法一的处理太粗躁,有没有更好的解决办法呢?使用轻量级工具emoji-java处理emoji表情字符

github地址:https://github.com/vdurmont/emoji-java
  具体使用方式,大家可以进入git中自行查看。

  3、有了上面两种方式,你是不是已经满足了,最为自己最推崇的emoji处理方式,下面才是重点,首先说一下上面两种方式存在的问题:第一种方式,数据经过转换,相当于加密,我们将无法直接查看到数据的原始内容,由其对于需要进行搜索的业务场景,将是一件很困难的事情;第二种方式,虽然避免了第一种方式存在的问题,但是它基于表情的对照表进行匹配转换的,也就意味着对于一些新表情,无法做到转换,这就会导致我们数据插入继续出现问题,这是它第一个问题,第二点在于它将表情转化为对应的匹配规则,说白一点就是转化为英文描述,就是这个转化,原本4个字节的表情,它可能给你转成了10个字节甚至更多。好了说了这么多下面我们看一下我最后的终极解决方法:

复制代码
/**

  • @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));
}

}
复制代码
  好了就先这样,欢迎大家提出不同的看法,已经好的解决方案。
原文地址https://www.cnblogs.com/AndroidJotting/p/11253202.html

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
阿里云服务器端口号设置
阿里云服务器初级使用者可能面临的问题之一. 使用tomcat或者其他服务器软件设置端口号后,比如 一些不是默认的, mysql的 3306, mssql的1433,有时候打不开网页, 原因是没有在ecs安全组去设置这个端口号. 解决: 点击ecs下网络和安全下的安全组 在弹出的安全组中,如果没有就新建安全组,然后点击配置规则 最后如上图点击添加...或快速创建.   have fun!  将编程看作是一门艺术,而不单单是个技术。
20063 0
07_NoSQL数据库之Redis数据库:Redis的高级应用之事务处理、持久化操作、pub_sub、虚拟内存
 事务处理 Redis对事务的支持目前还比较简单。Redis只能保证一个client发起的事务中的命令可以连续的执行,而中间不会插入其他client的命令。当一个client在一个连接中发出multi命令时,这个连接会进入一个事务上下文,该连接后续的命令不会立即执行,而是先放到一个队列中,当执行exec命令时,redis会顺序的执行队列中的所有命令。
1175 0
阿里云ECS云服务器初始化设置教程方法
阿里云ECS云服务器初始化是指将云服务器系统恢复到最初状态的过程,阿里云的服务器初始化是通过更换系统盘来实现的,是免费的,阿里云百科网分享服务器初始化教程: 服务器初始化教程方法 本文的服务器初始化是指将ECS云服务器系统恢复到最初状态,服务器中的数据也会被清空,所以初始化之前一定要先备份好。
16592 0
Android使用Room持久化SQLite
原文链接 前言 Android中提供了SQLite数据库进行数据的持久化 ,并提供了对应API访问数据库,而Room框架提供了SQLite数据访问抽象层,为高效的数据库访问层带来便捷 APP可以缓存用户数据,当APP离线时便从SQLite读取数据,当重...
1496 0
+关注
优惠码优惠
阿里云优惠码阿里云推荐券bieryun.com
202
文章
0
问答
文章排行榜
最热
最新
相关电子书
更多
JS零基础入门教程(上册)
立即下载
性能优化方法论
立即下载
手把手学习日志服务SLS,云启实验室实战指南
立即下载