mysql保存emoji表情问题-java

本文探讨了Emoji表情在MySQL utf8字符集下遇到的兼容性问题,并提供了两种解决方案:一是将数据库字符集升级为utf8mb4;二是通过urlencode或base64对Emoji进行转换,以便能在utf8下存储。

问题

无法保存emoji表情到MySQL(字符集为utf-8)?

原因

emoji表情也是utf-8编码,但是占用4个字节,而mysql的utf-8字符集的数据库每个字符只有3个字节,所以无法保存emoji表情到mysql数据库。

解决方法

一、修改数据库字符集为utf8mb4

在5.5.3版本之后的mysql数据库支持utf8mb4字符集,可以保存4个字节的emoji表情。需要修改数据库、表、字段的字符集为utf8mb4。

这是最简单有效的方法。

二、将emoji表情转换成可以保存的格式

我试过的有两种方式,一种是以urlencode转换,一种是以base64加密,都是可以将emoji表情保存为mysql数据库(utf-8)的方法,但也有很明显的缺陷:

(1)每次输入和输出都要进行加密和解密,会影响效率,虽然影响不大

(2)一个emoji表情,正常情况下只用一个字符就能保存,但urlencode处理后需要12字节(%03%25%17%37的格式),base64需要6字节(8J-Sjg的格式),除此之外还需正则识别的标志,比如[[8J-Sjg]],其中[[]]是为了正则表达式定位用的。另注意:若处理json格式的字符串,最好不要用[[]],可能保存数据库中的结果变成[["8J-Sjg"]]。

emoji表情的正则表达式

发现一个很不错的正则,实验后善未发现无法识别的表情(iOS ipad上实验)

input.replaceAll("[\\x{10000}-\\x{10ffff}\ud800-\udfff]", "");

 

来源:http://stackoverflow.com/questions/27820971/why-a-surrogate-java-regexp-finds-hypen-minus

 

样例

 

[java] view plain copy

print?

  1.  /** 
  2.  * @Description 将字符串中的emoji表情转换成可以在utf-8字符集数据库中保存的格式(表情占4个字节,需要utf8mb4字符集) 
  3.  * @param str 
  4.  *            待转换字符串 
  5.  * @return 转换后字符串 
  6.  * @throws UnsupportedEncodingException 
  7.  *             exception 
  8.  */  
  9. public static String emojiConvert1(String str)  
  10.         throws UnsupportedEncodingException {  
  11.     String patternString = "([\\x{10000}-\\x{10ffff}\ud800-\udfff])";  
  12.   
  13.     Pattern pattern = Pattern.compile(patternString);  
  14.     Matcher matcher = pattern.matcher(str);  
  15.     StringBuffer sb = new StringBuffer();  
  16.     while(matcher.find()) {  
  17.         try {  
  18.             matcher.appendReplacement(  
  19.                     sb,  
  20.                     "[["  
  21.                             + URLEncoder.encode(matcher.group(1),  
  22.                                     "UTF-8") + "]]");  
  23.         } catch(UnsupportedEncodingException e) {  
  24.             LOG.error("emojiConvert error", e);  
  25.             throw e;  
  26.         }  
  27.     }  
  28.     matcher.appendTail(sb);  
  29.     LOG.debug("emojiConvert " + str + " to " + sb.toString()  
  30.             + ", len:" + sb.length());  
  31.     return sb.toString();  
  32. }  
  33.   
  34. /** 
  35.  * @Description 还原utf8数据库中保存的含转换后emoji表情的字符串 
  36.  * @param str 
  37.  *            转换后的字符串 
  38.  * @return 转换前的字符串 
  39.  * @throws UnsupportedEncodingException 
  40.  *             exception 
  41.  */  
  42. public static String emojiRecovery2(String str)  
  43.         throws UnsupportedEncodingException {  
  44.     String patternString = "\\[\\[(.*?)\\]\\]";  
  45.   
  46.     Pattern pattern = Pattern.compile(patternString);  
  47.     Matcher matcher = pattern.matcher(str);  
  48.   
  49.     StringBuffer sb = new StringBuffer();  
  50.     while(matcher.find()) {  
  51.         try {  
  52.             matcher.appendReplacement(sb,  
  53.                     URLDecoder.decode(matcher.group(1), "UTF-8"));  
  54.         } catch(UnsupportedEncodingException e) {  
  55.             LOG.error("emojiRecovery error", e);  
  56.             throw e;  
  57.         }  
  58.     }  
  59.     matcher.appendTail(sb);  
  60.     LOG.debug("emojiRecovery " + str + " to " + sb.toString());  
  61.     return sb.toString();  
  62. }  

转载于:https://my.oschina.net/zhangph89/blog/1529023

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值