Java处理emoji
1.问题产生情况
我遇到这个问题是做微信开发的时候有些有用的头像用了微信的emoji表情,然而我的mysql数据库用的编码是utf8_general_ci,就是utf-8编码,结果也就报错误了。
2.为什么会出现这种原因
因为mysql的utf8编码的一个字符最多3个字节,但是一个emoji表情为4个字节,所以utf8不支持存储emoji表情。但是utf8的超集utf8mb4一个字符最多能有4字节,所以能支持emoji表情的存储。
3.解决方法之一
把你的数据库编码集设置为utf8mb4,无论是数据库还是表,还是字段。虽然会增加存储,但是这个可以忽略不计。
4.解决方法之二
有句话说得好,问题来了要么解决要么折中解决。如果有些原因你不能修改数据库编码之类的,你可以用java的一些插件,如emoji-java这种emoji表情插件对表情进行特殊处理,然后保存或者去掉表情,这也是一种解决方法哦。
最后来段代码
package com.mojxtang;
import org.apache.commons.lang3.StringUtils;
/**
* <pre>
* 本类的主要功能是将带有emoji的字符串,格式化成unicode字符串,并且提供可见unicode字符反解成emoji字符
*
*
* 相关识知点:
* <b>
* Unicode平面,
* BMP的字符可以使用charAt(index)来处理,计数可以使用length()
* 其它平面字符,需要用codePointAt(index),计数可以使用codePointCount(0,str.lenght())</b>
*
* Unicode可以逻辑分为17平面(Plane),每个平面拥有65536( = 216)个代码点,虽然目前只有少数平面被使
* 用。
* 平面0 (0000–FFFF): 基本多文种平面(Basic Multilingual Plane, BMP).
* 平面1 (10000–1FFFF): 多文种补充平面(Supplementary Multilingual Plane, SMP).
* 平面2 (20000–2FFFF): 表意文字补充平面(Supplementary Ideographic Plane, SIP).
* 平面3 (30000–3FFFF): 表意文字第三平面(Tertiary Ideographic Plane, TIP).
* 平面4 to 13 (40000–DFFFF)尚未使用
* 平面14 (E0000–EFFFF): 特别用途补充平面(Supplementary Special-purpose Plane, SSP)
* 平面15 (F0000–FFFFF)保留作为私人使用区(Private Use Area, PUA)
* 平面16 (100000–10FFFF),保留作为私人使用区(Private Use Area, PUA)
*
* 参考:
* 百度百科: https://baike.baidu.com/item/emoji/8154456?fr=aladdin
*emoji表情:http://www.fhdq.net/emoji/emojifuhao.html
* 杂项象形符号:1F300-1F5FF
* 表情符号:1F600-1F64F
* 交通和地图符号:1F680-1F6FF
* 杂项符号:2600-26FF
* 符号字体:2700-27BF
* 国旗:1F100-1F1FF
* 箭头:2B00-2BFF 2900-297F
* 各种技术符号:2300-23FF
* 字母符号: 2100–214F
* 中文符号: 303D 3200–32FF 2049 203C
* Private Use Area:E000-F8FF;
* High Surrogates D800..DB7F;
* High Private Use Surrogates DB80..DBFF
* Low Surrogates DC00..DFFF D800-DFFF E000-F8FF
* 标点符号:2000-200F 2028-202F 205F 2065-206F
* 变异选择器:IOS独有 FE00-FE0F
* </pre>
*/
public class EmojiCharacterUtil {
// 转义时标识
private static final char unicode_separator = '&';
private static final char unicode_prefix = 'u';
private static final char separator = ':';
private static boolean isEmojiCharacter(int codePoint) {
return (codePoint >= 0x2600 && codePoint <= 0x27BF) // 杂项符号与符号字体
|| codePoint == 0x303D || codePoint == 0x2049 || codePoint == 0x203C
|| (codePoint >= 0x2000 && codePoint <= 0x200F)//
|| (codePoint >= 0x2028 && codePoint <= 0x202F)//
|| codePoint == 0x205F //
|| (codePoint >= 0x2065 && codePoint <= 0x206F)//
/* 标点符号占用区域 */
|| (codePoint >= 0x2100 && codePoint <= 0x214F)// 字母符号
|| (codePoint >= 0x2300 && codePoint <= 0x23FF)// 各种技术符号
|| (codePoint >= 0x2B00 && codePoint <= 0x2BFF)// 箭头A
|| (codePoint >= 0x2900 && codePoint <= 0x297F)// 箭头B
|| (codePoint >= 0x3200 && codePoint <= 0x32FF)// 中文符号
|| (codePoint >= 0xD800 && codePoint <= 0xDFFF)// 高低位替代符保留区域
|| (codePoint >= 0xE000 && codePoint <= 0xF8FF)// 私有保留区域
|| (codePoint >= 0xFE00 && codePoint <= 0xFE0F)// 变异选择器
|| codePoint >= 0x10000; // Plane在第二平面以上的,char都不可以存,全部都转
}
/**
* 将带有emoji字符的字符串转换成可见字符标识
*/
public static String escape(String src) {
if (StringUtils.isBlank(src)) {
return src;
}
int cpCount = src.codePointCount(0, src.length());
int firCodeIndex = src.offsetByCodePoints(0, 0);
int lstCodeIndex = src.offsetByCodePoints(0, cpCount - 1);
StringBuilder sb = new StringBuilder(src.length());
for (int index = firCodeIndex; index <= lstCodeIndex; index++) {
int codepoint = src.codePointAt(index);
if (isEmojiCharacter(codepoint)) {
String hash = Integer.toHexString(codepoint);
sb.append(unicode_separator).append(hash.length()).append(unicode_prefix).append(separator)
.append(hash);
// hash 长度,4位1个字节
index += (hash.length() - 1) / 4;
} else {
sb.append((char) codepoint);
}
}
return sb.toString();
}
/** 解析可见字符标识字符串 */
public static String reverse(String src) {
// 查找对应编码的标识位
if (StringUtils.isBlank(src)) {
return src;
}
StringBuilder sb = new StringBuilder(src.length());
char[] sourceChar = src.toCharArray();
int index = 0;
while (index < sourceChar.length) {
if (sourceChar[index] == unicode_separator) {
if (index + 6 >= sourceChar.length) {
sb.append(sourceChar[index]);
index++;
continue;
}
// 自已的格式,与通用unicode格式不能互转
if (sourceChar[index + 1] >= '4' && sourceChar[index + 1] <= '6'
&& sourceChar[index + 2] == unicode_prefix && sourceChar[index + 3] == separator) {
int length = Integer.parseInt(String.valueOf(sourceChar[index + 1]));
char[] hexchars = new char[length]; // 创建一个4至六位的数组,来存储uncode码的HEX值
for (int j = 0; j < length; j++) {
char ch = sourceChar[index + 4 + j];// 4位识别码
if ((ch >= '0' && ch <= '9') || (ch >= 'a' && ch <= 'f')) {
hexchars[j] = ch;
} else { // 字符范围不对
sb.append(sourceChar[index]);
index++;
break;
}
}
sb.append(Character.toChars(Integer.parseInt(new String(hexchars), 16)));
index += (4 + length);// 4位前缀+4-6位字符码
} else if (sourceChar[index + 1] == unicode_prefix) { // 通用字符的反转
// 因为第二平面之上的,已经采用了我们自己转码格式,所以这里是固定的长度4
char[] hexchars = new char[4];
for (int j = 0; j < 4; j++) {
char ch = sourceChar[index + 2 + j]; // 两位识别码要去掉
if ((ch >= '0' && ch <= '9') || (ch >= 'a' && ch <= 'f')) {
hexchars[j] = ch; // 4位识别码
} else { // 字符范围不对
sb.append(sourceChar[index]);
index++;
break;
}
sb.append(Character.toChars(Integer.parseInt(String.valueOf(hexchars), 16)));
index += (2 + 4);// 2位前缀+4位字符码
}
} else {
sb.append(sourceChar[index]);
index++;
continue;
}
} else {
sb.append(sourceChar[index]);
index++;
continue;
}
}
return sb.toString();
}
public static String filter(String src) {
if (src == null) {
return null;
}
int cpCount = src.codePointCount(0, src.length());
int firCodeIndex = src.offsetByCodePoints(0, 0);
int lstCodeIndex = src.offsetByCodePoints(0, cpCount - 1);
StringBuilder sb = new StringBuilder(src.length());
for (int index = firCodeIndex; index <= lstCodeIndex;) {
int codepoint = src.codePointAt(index);
if (!isEmojiCharacter(codepoint)) {
System.err.println("codepoint:" + Integer.toHexString(codepoint));
sb.append((char) codepoint);
}
index += ((Character.isSupplementaryCodePoint(codepoint)) ? 2 : 1);
}
return sb.toString();
}
}
Java处理emoji的更多相关文章
- java过滤emoji表情
import java.util.regex.Matcher; import java.util.regex.Pattern; public class test { /** * 表情过滤 * */ ...
- java过滤emoji表情(成功率高)
转载自:http://blog.csdn.net/huangchao064/article/details/53283738 基本能过滤大部分的ios,安卓,微信emoji表情 有很多别的帖子搜出来很 ...
- Java转义emoji等特殊符号
写在前面 网上找了很多转emoji等方法,大多有两种方法 更改数据库编码格式为utf8mb4 过滤字符串中的emoji 都不是很优雅 更改数据库编码,势必影响其他数据库 过滤emoj效率比较低 处理E ...
- Java 中 Emoji 的正则表达式
一.emoji 的范围 查阅维基百科中 emoji 的说明 1. 杂项符号及图形 杂项符号及图形一共有768个字符,范围为: U+1F300 - U+1F5FF,在 Java 中正则表达式为: &qu ...
- java 处理emoji表情信息转换为String
2种方式实现: 注意:如果发现运行时java.lang.NoClassDefFoundError:异常就是缺少了jar包.添加对应的jar包就可以. 一.emoji-java-4.0.0.jar实现 ...
- java处理emoji(转)
最近对接ios.安卓客户端,需要处理emoji等表情符号,网上总结: 1.过滤掉emoji表情符 2.修改数据库的编码格式等,让其支持存储emoji 以下分别对两种方案进行描述: 第一种:过滤掉emo ...
- java转换emoji表情
/** * @Description 将字符串中的emoji表情转换成可以在utf-8字符集数据库中保存的格式(表情占4个字节,需要utf8mb4字符集) * @param str * 待转换字符串 ...
- Java 解决Emoji表情过滤问题(转载)
本文作者 我是周洲 原文链接 https://blog.csdn.net/u012904383/article/details/79376707 本人使用的是第三种引入jar的方法 问题: Emoji ...
- Java 解决Emoji表情过滤问题
Emoji表情从三方数据中获取没有过滤,导致存入DB的时候报错. 原因: UTF-8编码有可能是两个.三个.四个字节.Emoji表情是4个字节,而Mysql的utf8编码最多3个字节,所以数据插不进去 ...
随机推荐
- python 将列表嵌套字典的unicode字符串转换为str格式的字符串的方法
今天在进行django开发的过程中遇到了一个非常棘手的问题, 因为需求原因, 需要将一份数据存为json格式到数据库中, 如下面这种格式: list_1 = [{"name":&q ...
- 蹭你wifi后 我竟然干了这样的事
前言:故事发生在前两天,我们去参观工业园区内一家电商公司. 去参观他们公司的时候,我说要用下无线网,他们技术说密码就是他们的网站域名,我一脸懵逼表示我不知道域名,然后对方接过我手机给我连上了他们wif ...
- FTP枢轴攻击
简单来说,这是攻击者可以利用属于不同网络的那些系统的攻击. 本文作者:jishuzhain 对于这种攻击,攻击者需要利用主服务器来帮助攻击者将自己添加到本地网络中,然后攻击者就可以将客户端系统进行定位 ...
- 【vue】——vue.js 获取当前 自定义属性值
假设有一个标签h5, 我们给它添加了一个自定义属性值,(item.id是从动态添加的) 点击h5 标签,如何才能获取当前对应的自定义属性值呢? 想当然的我最开始这样写: <h5 class=&q ...
- [推荐] 网络侦查工具 NMAP 简单入门
[推荐] 网络侦查工具 NMAP 简单入门 # 前言 作为一只运维开发,总是避不开要和网络打交道的.尤其是当自身能力到达瓶颈,开始从事云计算以求突破.会有搭建多台虚拟机的需要,这时候如果在手工的查询 ...
- 46.ActiveMQ开篇(Hello World、安全认证、Connection、Session、MessageProducer、MessageConsumer)
要给有能力的人足够的发挥空间,公司可以养一些能力平平甚至是混日子的人,但绝不能让这些人妨碍有能力的人,否则这样的环境不留也罢. 一.背景介绍 CORBA\DCOM\RMI等RPC中间件技术已经广泛应用 ...
- 静态网页、动态网页、apache和tomcat之间区别和联系
1.静态网页 静态网页:在网站设计中, 纯粹的HTML(标准通用标志语言下的一个应用)格式的网页通常被称为"静态网页",静态网页是标准的HTML文件,它的拓拓展名是.html或者. ...
- Developer Friendly | 基础设施即代码的事实标准Terraform已支持京东云!
Developer Friendly | 基础设施即代码的事实标准Terraform已支持京东云! Chef.Puppet.Ansible.SaltStack 都可以称为配置管理工具,这些工具的主要目 ...
- SQL语句02(连表查询)
---恢复内容开始--- sql1992sql分类 1.笛卡尔积 (表乘表) 例:select * from emp,dept; 2.等值连接 表的连接条件使用“=” 例:select * ...
- linux 命令 htop & 重定向 top, bashrc文件
最近在用linux服务器跑程序,有几条linux命令还蛮重要的,总结一下: 1. 直接跑代码: python test.py 2. 若想程序在后台跑,即使本地和服务器断开也能运行: nohup pyt ...