欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

MySql 中文写入数据库乱码及Incorrect string value: '\xF0\x9F...' for column 'XXX' at row 1解决

程序员文章站 2022-03-09 14:34:19
一、中文写入乱码问题 我输入的中文编码是 urf8 的,建的库是 urf8 的,但是插入MySQL总是乱码,一堆"???????????????????????"。可以使用以下的方式试试决解: 原url地址是 改为 就OK了。 二、Incorrect string value: '\xF0\x9F. ......

一、中文写入乱码问题


我输入的中文编码是 urf8 的,建的库是 urf8 的,但是插入mysql总是乱码,一堆"???????????????????????"。可以使用以下的方式试试决解:

原url地址是

jdbc:mysql://localhost:3306/数据库名

改为

jdbc:mysql://localhost:3306/数据库名?useunicode=true&characterencoding=utf-8

就ok了。

二、incorrect string value: '\xf0\x9f...' for column 'xxx' at row 1


做有关微信公众账号的项目时,报incorrect string value: '\xf0\x9f\x98\x92' for column 'nikename' at row 1,而所有的字符编码都是 utf8,使用的数据库是 mysql,在测试环境用得好好的,部署到线上后(使用的集群是阿里巴巴的,数据库服务器也是使用它们的,mysql 服务器版本是 5.5.18),就报这个错了,并且这个错,时而出现,时而不出现

emoji表情字符现在在app已经广泛支持了。但是mysql的utf8编码对emoji字符的支持却不是那么好。所以我们经常会遇到这样的异常:

java.sql.sqlexception: incorrect string value: '\xf0\x9f\x98\x8e' for column 'nick' at row 1

原因是mysql里 urf8 编码最多只能支持3个字节,而emoji表情字符使用的 urf8 编码,很多都是4个字节,有些甚至是6个字节。

解决的方案有两种:

  1. 使用 utf8mb4 的 mysql 编码来容纳这些字符;
  2. 过滤掉这些特殊的表情字符。

方法1:使用utf8mb4的mysql编码来容纳这些字符


注意:要使用 utf8mb4 类型,首先要保证mysql版本要不低于 mysql 5.5.3。

第一步:在mysql的安装目录下找到my.ini,作如下修改:

[client] 
default-character-set = utf8mb4 
[mysql] 
default-character-set = utf8mb4 
[mysqld] 
character-set-client-handshake = false 
character-set-server = utf8mb4 
collation-server = utf8mb4_unicode_ci 
init_connect='set names utf8mb4'

修改后重启mysql。

第二步:将已经建好的表也转换成 utf8mb4

alter table table_name convert to character set utf8mb4 collate utf8mb4_bin; 

将 table_name 替换成你的表名。然后就ok了。

网上流传的一个版本增加了一个步骤,就是以 root 身份登录 mysql,修改环境变量,将

character_set_client,character_set_connection,character_set_database,character_set_results,character_set_server

都修改成 utf8mb4。不过我没有做这一步,也正常,所以可能是这一步是多余的。

方法2:过滤掉这些特殊的字符


import org.apache.commons.lang.stringutils;

public class charutil {
    /**
     * 替换四个字节的字符 '\xf0\x9f\x98\x84\xf0\x9f)的解决方案 ��
     */
    public static string removefourchar(string content) {
        byte[] conbyte = content.getbytes();
        for (int i = 0; i < conbyte.length; i++) {
            if ((conbyte[i] & 0xf8) == 0xf0) {
                for (int j = 0; j < 4; j++) {
                    conbyte[i + j] = 0x30;// 0x30 int=48   字符=0
                }
                i += 3;
            }
        }
        content = new string(conbyte);
        return content.replaceall("0000", "");
    }

    /**
     * 将emoji表情替换成*
     * @return 过滤后的字符串
     * 过滤的方式很简单,直接使用正则表达式匹配编码范围,然后替换就行了。
     */
    public static string filteremoji(string source) {
        if (stringutils.isnotblank(source)) {
            return source.replaceall("[\\ud800\\udc00-\\udbff\\udfff\\ud800-\\udfff]", "*");
        } else {
            return source;
        }
    }

    public static void main(string[] arg) {
        try {
            system.err.println("测试->将emoji表情替换成*");
            string text = "this is a smiley \ud83c\udfa6 face\ud860\udd5d \ud860\ude07 \ud860\udee2 \ud863\udcca \ud863\udccd \ud863\udcd2 \ud867\udd98 ";
            system.out.println(text);
            system.out.println(text.length());
            system.out.println(text.replaceall("[\\ud83c\\udc00-\\ud83c\\udfff]|[\\ud83d\\udc00-\\ud83d\\udfff]|[\\u2600-\\u27ff]", "*"));
            system.out.println(filteremoji(text));
            //输出结果
            //this is a smiley �� face�� �� �� �� �� �� �� 
            //45
            //this is a smiley * face�� �� �� �� �� �� �� 
            //this is a smiley * face* * * * * * * 

            system.err.println("测试->替换四个字节的字符 '\\xf0\\x9f\\x98\\x84\\xf0\\x9f)的解决方案 ��");
            string title = "ff的范德萨分��������llfldakf;dsk。f������������daslfjdsa;lfkjdsd'j'l'f'k'd'j'sa'l'k";
            system.out.println(removefourchar(title));
            //输出结果:ff的范德萨分llfldakf;dsk。fdaslfjdsa;lfkjdsd'j'l'f'k'd'j'sa'l'k

        } catch (exception ex) {
            ex.printstacktrace();
        }
    }
}