MySQL数据库如何存储Emoji表情

Store Emoji in MySQL

今天,在测试博客的评论功能时,报了一个这样的异常:

Caused by: java.sql.SQLException: Incorrect string value: '\xF0\x9F\x98\x84' for column 'content' at row 1

原因是我试图发表一个带有Emoji表情的评论:

发表一个带有Emoji表情的评论

怎么会出现这样的问题呢?

原因分析

从抛出的异常来看,是数据库不支持 😄 这个Emoji表情,认为它是一个不合法的字符串。我们知道,字符串在计算机中也是以二进制形式传输和存储的,但是同样的二进制数据,用不同的编码方式解析,会得到不同的字符串。

例如 F09F9884 这四个字节,我们在Java中用常见的一些编码方式来解析它:

byte[] bytes = { (byte) 0xF0, (byte) 0x9F, (byte) 0x98, (byte) 0x84 }; System.out.println(new String(bytes, "UTF-16")); System.out.println(new String(bytes, "UTF-8")); System.out.println(new String(bytes, "GBK")); System.out.println(new String(bytes, "GB2312"));

得到的结果分别如下:

预 😄 馃槃 ���

可以看到,对于 F09F9884 这四个字节,我们只有用UTF-8编码才能将它解析成正确的字符串。但是,我在MySQL数据库中设置的字符集也是utf8,为什么还会报错呢?

追根溯源,我们在MySQL官方的utf8字符集文档中得到一个结论:MySQL中的utf8是utf8mb3字符集的别名,并没有真正地实现UTF-8编码。utf8mb3字符集用1~3个字节来表示一个字符,而我们前面的这个Emoji表情字符 😄 则需要4个字节才能表示,因此MySQL的utf8字符集就不支持这样的Emoji表情字符。

解决方式

在官方文档中,MySQL也告诉我们,utf8mb3将会在未来的版本中移除,最好的方式是直接使用utf8mb4字符集。utf8mb4字符集用1~4个字节来表示一个字符,能正确地支持UTF-8编码的字符串。

所以,我只需要将数据库中评论内容的字符集设置成utf8mb4即可:

ALTER TABLE `comment` CHANGE COLUMN `content` `content` VARCHAR(1000) CHARACTER SET 'utf8mb4' NOT NULL COMMENT '内容';

这样,评论内容就可以支持Emoji表情了:

支持Emoji表情的评论

 

 

文章评论
${fromAuthor ? '郄正元' : '游客'} 作者 ${gmtCreate}
${content}
${subList.length}
发表评论
${commentToArticle ? '' : parentContent}
字数:0/${maxCommentLength}
该邮箱地址仅用于接收其他用户的回复提醒,不会泄露