Java Unicode编码 及 Mysql utf8 utf8mb3 utf8mb4 的区别与utf8mb4的过滤

时间:2024-01-14 12:27:50

UTF-8简介

UTF-8(8-bit Unicode Transformation Format)是一种针对Unicode的可变长度字符编码,也是一种前缀码。它可以用来表示Unicode标准中的任何字符,且其编码中的第一个字节仍与ASCII兼容,这使得原来处理ASCII字符的软件无须或只须做少部分修改,即可继续使用。因此,它逐渐成为电子邮件、网页及其他存储或发送文字的应用中,优先采用的编码。

UTF-8使用一至四个字节为每个字符编码(2003年11月UTF-8被RFC 3629重新规范,只能使用原来Unicode定义的区域,U+0000到U+10FFFF,也就是说最多四个字节):

  • 128个US-ASCII字符只需一个字节编码(Unicode范围由U+0000至U+007F)。

  • 带有附加符号的拉丁文、希腊文、西里尔字母、亚美尼亚语、希伯来文、阿拉伯文、叙利亚文及它拿字母则需要两个字节编码(Unicode范围由U+0080至U+07FF)。

  • 其他基本多文种平面BMP, Basic Multilingual Plane)中的字符(这包含了大部分常用字,例如CJVK常用字字符集 —— Chinese, Japanese, Vietnam, Korean)使用三个字节编码(Unicode范围由U+0800至U+FFFF)。

  • 其他使用极少的Unicode 辅助平面(Supplementary Multilingual Plane)的字符使用四字节编码(Unicode范围由U+10000至U+10FFFF,主要包括不常用的CJK字符, 数学符号, emoji表情等)。

utf-8编码方式
Java Unicode编码 及 Mysql utf8 utf8mb3 utf8mb4 的区别与utf8mb4的过滤

unicode code point table
Java Unicode编码 及 Mysql utf8 utf8mb3 utf8mb4 的区别与utf8mb4的过滤

参考与扩展
* UTF-8 https://en.wikipedia.org/wiki/UTF-8, 中文版 https://zh.wikipedia.org/wiki/UTF-8*
* Plane_(Unicode) https://en.wikipedia.org/wiki/Plane_%28Unicode%29*
* CJK characters https://en.wikipedia.org/wiki/CJK_characters*
* Emoji https://en.wikipedia.org/wiki/Emoji*

UTF-8与Unicode的关系

utf8编码是unicode编码的一种实现,可以简单的理解为unicode编码定义一串数字来一一对应我们用到的字符,utf8定义了如何将unicode定义的这串数字保存到内存中。 另外需要强调的是utf8是一种变长的编码规范
unicode 的范围 U+0000 - U+10FFFF。

参考与扩展
** Unicode https://en.wikipedia.org/wiki/Unicode*

Mysql中的 UTF-8、UTF8mb3, UTF8mb4

utf8mb4, MySQL在5.5.3之后增加了这个utf8mb4的编码,mb4就是most bytes 4的意思,专门用来兼容四字节的unicode字符。
mysql中的utf8,就是最大3字节的unicode字符,也就是mysql中的utf8mb3.

参考
mysql-charset-unicode-utf8mb3 https://dev.mysql.com/doc/refman/5.5/en/charset-unicode-utf8mb3.html and https://dev.mysql.com/doc/refman/5.5/en/charset-unicode-utf8.html*
mysql-charset-unicode-utf8mb4 https://dev.mysql.com/doc/refman/5.5/en/charset-unicode-utf8mb4.html*

表示范围

说明 mysql utf8 / utf8mb3 mysql utf8mb4
max bit 3 4
范围 基本多文种平面 + US-ASCII 辅助平面(Supplementary) + 基本多文种平面 + US-ASCII
unicode范围 U+0000 - U+FFFF U+0000 - U+10FFFFF
常见字符 英文字母,CJK大部分常用字等 CJK非常用字,数学符号,emoji表情等

那么问题来了,如果用了utf8mb3编码的mysql数据库,在插入一些4字节长的字符时就会报错(形如:"java.sql.SQLException: Incorrect string value: '\xF0\x9F\x94\x91\xE6\x9D...' for column 'core_data' at row 1" 的错误),后文会介绍如何在Java中过滤掉这些字符。

要在Java中过滤Mysql的utf8mb4,必须弄清Java是如何支持Unicode编码,接下来徐徐展开......

编码简介

下面先介绍几个概念:character(字符), character set(字符集), coded character set(字符编码集), code point(代码点), code space(代码空间),character encoding scheme(字符编码方案),code unit(编码单元),和3种Unicode常用的编码方式。

  • character——字符,'a', '€', '中' 等, 都是一个字符
  • character set——字符集,字符的集合
  • coded character set——字符编码集,为每一个字符指定一个唯一的数字用来表示这个字符,这些数字组成的集合就是字符编**码集合,Unicode就是一个字符编码集
  • code point——代码点,是一个数字,用来表示字符集中的一个字符,也就是字符编码集中的一个数,例如 Unicode 编码中, 'A'的code point就是65(在Unicode中通常写作 U+0041)
  • code space——代码空间,就是一个编码集中,code point的范围, 例如 Unicode 编码的 code space 就是 0x0000 - 0x10FFFF
  • character encoding scheme——字符编码方案,它定义了将字符用一个或多个固定长度的代码单元的方案,如前文提到的"utf-8编码方式"就是一个字符编码方案,其它的还有UTF16,UTF32,GBK等等
  • code unit——编码单元,就是编码方案中固定长度的最小编码单元,如UTF8的编码单元是1bit,UTF16是2bit,UTF32是4bit,

Unicode常用的三种编码方式 UTF-8, UTF-16, UTF-32, 下面以辅助平面中的字符'