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

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

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

  1. 1.URLEncoder.encode(String s, String enc)
  2. 使用指定的编码机制将字符串转换为 application/x-www-form-urlencoded 格式
  3.  
  4. URLDecoder.decode(String s, String enc)
  5. 使用指定的编码机制对 application/x-www-form-urlencoded 字符串解码。

  2、方法一的处理太粗躁,有没有更好的解决办法呢?使用轻量级工具emoji-java处理emoji表情字符

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

  具体使用方式,大家可以进入git中自行查看。

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

  1. /**
  2. * @Author: gaoshang
  3. * @Description:
  4. * @Date: 2019/7/19
  5. */
  6. public class EmojiUtil {
  7.  
  8. /**
  9. * 将文本中的表情转为十六进制
  10. * <p>
  11. *
  12. * @param input
  13. * @return
  14. */
  15. public static String parseFromAliases(String input) {
  16. if (input == null) {
  17. return input;
  18. }
  19.  
  20. return stringToUnicode(input);
  21. }
  22.  
  23. /**
  24. * 将文本中的十六进制转为表情
  25. * <p>
  26. *
  27. * @param input
  28. * @return
  29. */
  30. public static String parseToAliases(String input) {
  31. if (input == null) {
  32. return input;
  33. }
  34.  
  35. return unicodeToString(input);
  36. }
  37.  
  38. /**
  39. * 字符串转unicode
  40. *
  41. * @param str
  42. * @return
  43. */
  44. public static String stringToUnicode(String str) {
  45. StringBuilder sb = new StringBuilder();
  46. StringBuilder cacheSB = new StringBuilder();
  47. char[] c = str.toCharArray();
  48. for (int i = 0; i < c.length; i++) {
  49. if (!isEmojiCharacter(c[i])) {
  50. if (cacheSB.length() > 0) {
  51. sb.append("\\u").append(cacheSB);
  52. cacheSB.delete(0, cacheSB.length());
  53. }
  54.  
  55. sb.append("\\u").append("[").append(Integer.toHexString(c[i])).append("]");
  56. } else {
  57. if (c[i] == '[' || c[i] == '\\' || c[i] == ']') {
  58. if (cacheSB.length() > 0) {
  59. sb.append("\\u").append(cacheSB);
  60. cacheSB.delete(0, cacheSB.length());
  61. }
  62. sb.append("\\u").append(c[i]);
  63. } else {
  64. cacheSB.append(c[i]);
  65. }
  66. }
  67. }
  68. if (cacheSB.length() > 0) {
  69. if (sb.length() > 0) {
  70. sb.append("\\u");
  71. }
  72. sb.append(cacheSB);
  73. }
  74. return sb.toString();
  75. }
  76.  
  77. /**
  78. * unicode转字符串
  79. *
  80. * @param unicode
  81. * @return
  82. */
  83. public static String unicodeToString(String unicode) {
  84. StringBuilder sb = new StringBuilder();
  85. String[] hex = unicode.split("\\\\u");
  86. for (int i = 0; i < hex.length; i++) {
  87. if (hex[i].indexOf("[") == 0 && hex[i].indexOf("]") == hex[i].length() - 1) {
  88. try {
  89. int index = Integer.parseInt(hex[i].substring(1, hex[i].length() - 1), 16);
  90. sb.append((char) index);
  91. } catch (NumberFormatException e) {
  92. sb.append(hex[i]);
  93. }
  94. } else {
  95. sb.append(hex[i]);
  96. }
  97. }
  98. return sb.toString();
  99. }
  100.  
  101. private static boolean isEmojiCharacter(char codePoint) {
  102. return (codePoint == 0x0) || (codePoint == 0x9) || (codePoint == 0xA)
  103. || (codePoint == 0xD)
  104. || ((codePoint >= 0x20) && (codePoint <= 0xD7FF))
  105. || ((codePoint >= 0xE000) && (codePoint <= 0xFFFD))
  106. || ((codePoint >= 0x10000) && (codePoint <= 0x10FFFF));
  107. }
  108.  
  109. }

  好了就先这样,欢迎大家提出不同的看法,已经好的解决方案。

Java emoji持久化mysql的更多相关文章

  1. 《精通Hibernate:Java对象持久化技术详解》目录

    图书信息:孙卫琴 电子工业出版社 第1章 Java应用分层架构及软件模型: 1.1 应用程序的分层体系结构 1.1.1 区分物理层和逻辑层 1.1.2 软件层的特征 1.1.3 软件分层的优点 1.1 ...

  2. java emoji表情存储解决方案

    1.问题产生情况 我遇到这个问题是做微信开发的时候有些有用的头像用了微信的emoji表情,然而我的mysql数据库用的编码是utf8_general_ci,就是utf-8编码,结果也就报错误了. 2. ...

  3. Java 数据持久化系列之JDBC

    前段时间小冰在工作中遇到了一系列关于数据持久化的问题,在排查问题时发现自己对 Java 后端的数据持久化框架的原理都不太了解,只有不断试错,因此走了很多弯路.于是下定决心,集中精力学习了持久化相关框架 ...

  4. Java 数据持久化系列之池化技术

    在上一篇文章<Java 数据持久化系列之JDBC>中,我们了解到使用 JDBC 创建 Connection 可以执行对应的SQL,但是创建 Connection 会消耗很多资源,所以 Ja ...

  5. Java 数据持久化系列之 HikariCP (一)

    在上一篇<Java 数据持久化系列之池化技术>中,我们了解了池化技术,并使用 Apache-common-Pool2 实现了一个简单连接池,实验对比了它和 HikariCP.Druid 等 ...

  6. java jdbc 连接mysql数据库 实现增删改查

    好久没有写博文了,写个简单的东西热热身,分享给大家. jdbc相信大家都不陌生,只要是个搞java的,最初接触j2ee的时候都是要学习这么个东西的,谁叫程序得和数据库打交道呢!而jdbc就是和数据库打 ...

  7. JSP 实现 之 调用java方法实现MySQL数据库备份和恢复

    package cn.qm.db; import java.io.BufferedReader; import java.io.DataInputStream; import java.io.IOEx ...

  8. 点评阿里JAVA手册之MySQL数据库 (建表规约、索引规约、SQL语句、ORM映射)

    下载原版阿里JAVA开发手册  [阿里巴巴Java开发手册v1.2.0] 本文主要是对照阿里开发手册,注释自己在工作中运用情况. 本文内容:MySQL数据库 (建表规约.索引规约.SQL语句.ORM映 ...

  9. 第68节:Java中的MYSQL运用从小白到大牛

    第68节:Java中的MYSQL运用从小白到大牛 前言 学习java必备要求,学会运用!!! 常见关系化数据库 BootStrap是轻量级开发响应式页面的框架,全局css组件,js插件.栅格系统是将页 ...

随机推荐

  1. 数组Array

    数组Array是最基本的数据结构,在内存中为一段定长连续内存,很多编程语言都有实现. 一.一维数组 下面代码实现了一维数组和它的遍历. clear并非清空数组,而是采用具体值对数组进行初始化. imp ...

  2. 常用URL分享,实用地址

    常用地址 文库文档免费下载地址1:http://www.hiwenku.com/ 文库文档免费下载下载2:http://www.20009.net/wk.html google地图拾取器:http:/ ...

  3. 点菜网---Java开源生鲜电商平台-系统架构图(源码可下载)

    点菜网---Java开源生鲜电商平台-系统架构图(源码可下载) 1.点菜网-生鲜电商平台的价值与定位. 生鲜电商平台是一家致力于打造全国餐饮行业智能化.便利化.平台化与透明化服务的创新型移动互联网平台 ...

  4. Ubuntu 配置docker镜像加速器

    1. 安装/升级Docker客户端 推荐安装1.10.0以上版本的Docker客户端,参考文档 docker-ce 2. 配置镜像加速器 针对Docker客户端版本大于 1.10.0 的用户 您可以通 ...

  5. NoSQL数据库兴起

    前言 近几年NoSQL数据库兴起,各种新的产品层出不穷,在此学习下NoSQL的基本理论,并认识下常见的NoSQL数据库. 一 NoSQL数据库兴起的原因 随着大数据技术兴起和Web2.0时代的到来.传 ...

  6. hdoj2036 改革春风吹满地——叉积

    利用向量积(叉积)计算三角形的面积和多边形的面积 关于叉积计算三角形面积和多边形面积 Problem Description " 改革春风吹满地, 不会AC没关系; 实在不行回老家, 还有一 ...

  7. shell遍历文件

    取文件每行的数据,需要按列取  可以 sed 加管道 使用 awk 取列 platform="list.txt" line=`grep -vc '^$' $platform` ; ...

  8. Ruby字符串(2):String方法详细整理

    String方法整理 官方手册 类方法 new new(str="") → new_str new(str="", encoding: enc) → new_s ...

  9. Smobiler与Windows的异步回调差别

    Smobiler与Windows的异步回调差别--基于.NET的APP开发和Windows开发差别 基于.NET的APP开发和Windows开发,异步回调差别 Windows app开发 异步回调 S ...

  10. 分析了16年的福利彩票记录,原来可以用Python这么买彩票

    目录 0 引言 1 环境 2 需求分析 3 代码实现 4 后记 0 引言 上周被一则新闻震惊到了,<2454万元大奖无人认领!福彩史上第二大弃奖在广东中山产生 >,在2019年5月2日开奖 ...