java.sql.SQLException: Incorrect string value: '\xF0\x9F\x92\x94' for column '*****' at row 1
使用Mysql服务器的utf8字符编码,在存入移动端emoji表情时会报异常:
-
Caused by: java.sql.SQLException: Incorrect string value: '\xF0\x9F\x98\x84' for column 'content' at row 1
-
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1074)
-
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:4096)
-
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:4028)
-
at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:2490)
-
at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2651)
-
at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2734)
-
at com.mysql.jdbc.PreparedStatement.executeInternal(PreparedStatement.java:2155)
-
at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:2458)
原因:mysql的utf8编码的一个字符最多3个字节,但是一个emoji表情为4个字节,所以utf8不支持存储emoji表情,导致报错.
解决办法:
一.服务器端转换数据库存储编码
数据库目前采用的编码为UTF8, 转换为可支持4个字节的utf8mb4_unicode编码。
如图所示:
利:客户端存储和请求数据的时候不需要都去做转换
弊:1)转换编码格式可能会导致现有数据库的数据发生乱码;
2)转换编码格式之后,可能对后续的全文搜索功能有影响,大多数中文搜索引擎支持的编码格式为UTF-8;
3)若Android端的编码与数据库转换后的编码不符,将对Android端产生同样的问题。
二.客户端转换编码
客户端输入内容时候,统一存储为服务端数据库支持的编码;客户端请求内容的时候,需要根据客户端支持的编码对请求到的数据进行相应的转换
如代码所示:
-
public class EmojiConverterUtil {
-
-
/**
-
* @Description 将字符串中的emoji表情转换成可以在utf-8字符集数据库中保存的格式(表情占4个字节,需要utf8mb4字符集)
-
* @param str
-
* 待转换字符串
-
* @return 转换后字符串
-
* @throws UnsupportedEncodingException
-
* exception
-
*/
-
public static String emojiConvert1(String str)
-
{
-
String patternString = "([\\x{10000}-\\x{10ffff}\ud800-\udfff])";
-
-
Pattern pattern = Pattern.compile(patternString);
-
Matcher matcher = pattern.matcher(str);
-
StringBuffer sb = new StringBuffer();
-
while(matcher.find()) {
-
try {
-
matcher.appendReplacement(
-
sb,
-
"[["
-
+ URLEncoder.encode(matcher.group(1),
-
"UTF-8") + "]]");
-
} catch(UnsupportedEncodingException e) {
-
}
-
}
-
matcher.appendTail(sb);
-
return sb.toString();
-
}
-
-
/**
-
* @Description 还原utf8数据库中保存的含转换后emoji表情的字符串
-
* @param str
-
* 转换后的字符串
-
* @return 转换前的字符串
-
* exception
-
*/
-
public static String emojiRecovery2(String str){
-
String patternString = "\\[\\[(.*?)\\]\\]";
-
-
Pattern pattern = Pattern.compile(patternString);
-
Matcher matcher = pattern.matcher(str);
-
-
StringBuffer sb = new StringBuffer();
-
while(matcher.find()) {
-
try {
-
matcher.appendReplacement(sb,
-
URLDecoder.decode(matcher.group(1), "UTF-8"));
-
} catch(UnsupportedEncodingException e) {
-
-
}
-
}
-
matcher.appendTail(sb);
-
return sb.toString();
-
}
-
-
-
}
利:减少服务器端转换编码带来的风险和压力
弊:客户端需要根据不同的设备系统自行做编码转换
注意: 这两种方案我都自己试验过,如果服务器时自己的话,我觉得采取第一种方案挺方便的,也不需要编码什么的,转来转去。如果数据时存储在他人服务器上的(比如阿里云),但是别人的服务器不允许存储emoji,那么我觉得采取第二种方案会好很多.
参考博客来源:https://blog.csdn.net/u010839779/article/details/45559291