使用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

  参考博客来源:https://www.cnblogs.com/shihaiming/p/5833244.html

Logo

更多推荐