Java emoji持久化mysql过程详解

作者:小破孩123 时间:2023-10-10 23:11:49 

前言

好久没有更新博客了,今天和大家分享一个关于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

标签:java,emoji,持久化,mysql
0
投稿

猜你喜欢

  • 详解JAVA动态代理

    2023-11-24 22:52:04
  • Java分页查询--分页显示(实例讲解)

    2023-02-05 11:07:15
  • Java Swing编写一个简单的计算器软件

    2023-08-12 06:24:04
  • 详解Java线程同步器CountDownLatch

    2023-08-23 18:42:39
  • Java中io流解析及代码实例

    2023-08-22 16:46:48
  • android开发仿ios的UIScrollView实例代码

    2023-08-07 01:55:20
  • Spring3 整合MyBatis3 配置多数据源动态选择SqlSessionFactory详细教程

    2023-03-21 21:22:27
  • java Hibernate多对多映射详解及实例代码

    2023-07-02 07:24:40
  • Java实现用户管理系统

    2023-08-26 17:18:21
  • Java设计模式之Strategy模式

    2023-11-21 03:58:22
  • 你知道在Java中Integer和int的这些区别吗?

    2023-09-04 02:50:18
  • 浅谈Maven的安装及修改为阿里云下载依赖

    2023-08-05 08:30:37
  • java实现文件变化监控的方法(推荐)

    2023-11-08 01:18:26
  • SpringBoot v2.2以上重复读取Request Body内容的解决方案

    2022-06-27 11:00:16
  • Android kotlin使用注解实现防按钮连点功能的示例

    2023-07-02 11:58:06
  • spring mvc 实现获取后端传递的值操作示例

    2023-08-10 12:55:52
  • 关于SpringCloudStream配置问题

    2023-08-08 20:12:00
  • Java KindEditor粘贴图片自动上传到服务器功能实现

    2023-08-07 01:42:33
  • Spring MVC深入学习之启动初始化过程

    2023-07-16 07:04:21
  • 详解java设计模式中的门面模式

    2021-08-17 18:16:25
  • asp之家 软件编程 m.aspxhome.com