最近线上碰到玩家反馈,苹果手机创建游戏角色或者改名的时候,如果名字中包含emoji表情,会导致我们数据库插入的时候报错。原因是数据库的utf-8最多支持三个字节,但是emoji表情则是4个字节(有一些繁体的汉字也是四个字节),导致插入数据库的时候不识别乱码报错。解决方案大致有如下三种:
- 改变数据库的编码格式为utf8mb4。 utf8mb4 是 utf8 的超集并完全兼容utf8,能够用四个字节存储更多的字符。mb4即 most bytes 4。 MySQL在 5.5.3 之后的版本才支持utf8mb4。
show variables like '%character%';
可以查看mysql定义的编码格式。而修改的方法也很多,一般是修改my.ini文件(linux默认下是在/etc/my.cnf这里),然后重启mysql。这种方法并不能从根本解决这个问题,特殊情况下还是会报错。
更改数据库编码:ALTER DATABASE caitu99 CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
更改表编码:ALTER TABLE TABLE_NAME CONVERT TO CHARACTER SET utf8mb4 COLLATEutf8mb4_general_ci;
————————————————
版权声明:本文为CSDN博主「jerry-89」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/eagle89/article/details/82148751
- 前端可以进行输入法的控制,就像限制只输入汉字或者英文一样,这个这里不予讨论。
- 解析输入字符,进行拦截。这个我们重点讨论一下。
UNICODE编码
Unicode 它是一个字符集,记录着世界上所有字符对应的一个数字。也是对于计算机语言二进制对应的字符的一个统一的标准。Unicode 没有规定字符对应的二进制码如何存储,所以,为了解决这块问题,有很多流行的编码格式诞生,比如UTF-8和UTF-16 。
UTF-8编码
UTF-8 是目前互联网上使用最广泛的一种 Unicode 编码方式,它的最大特点就是可变长。它可以使用 1 - 4 个字节表示一个字符,根据字符的不同变换长度,这样可以有效的节约空间。编码规则如下:
-
对于单个字节的字符,第一位设为 0,后面的 7 位对应这个字符的 Unicode 码点。因此,对于英文中的 0 - 127 号字符,与 ASCII 码完全相同。这意味着 ASCII 码那个年代的文档用 UTF-8 编码打开完全没有问题。
-
对于需要使用 N 个字节来表示的字符(N > 1),第一个字节的前 N 位都设为 1,第 N + 1 位设为0,剩余的 N - 1 个字节的前两位都设为 10,剩下的二进制位则使用这个字符的 Unicode 码点来填充。比如4个字节的emoji表情,对应的格式就是11110xxx 10xxxxxx 10xxxxxx 10xxxxxx。具体的UTF-8所需字节区间和对应存储字节的格式如下:
之所以这样规定,是为了方便我解码的时候去拉取对应的数量的字节去拼成char:如果一个字节的第一位是 0 ,则说明这个字节对应一个字符;如果一个字节的第一位1,那么连续有多少个 1,就表示该字符占用多少个字节。
emoji表情区块
根据维基百科的描述,2010年10月发布的Unicode 6.0版首次收录emoji编码,其中582个emoji符号,66个已在其他位置编码,保留作相容用途的emoji符号。在Unicode 9.0 用22区块中共计1,126个字符表示emoji,其中1,085个是独立emoji字符,26个是用来显示旗帜的区域指示符号以及 12 个(#, * and 0-9)键帽符号。
杂项符号及图形768个字符中有637是emoji;增补符号及图形82个字符中有80个是emoji;所有80个表情符号都是emoji;交通及地图符号103个字符中有92个是emoji;杂项符号256个字符中有80个是emoji;装饰符号192个字符中有33个是emoji。所以emoji区间还是比较繁杂的,不像中文就是固定的\u4e00-\u9fa5 (中文utf-8区间)
,大家有兴趣的可以点击这里查看详细。
具体区间细分如下:
- 杂项符号及图形,范围为: U+1F300 ~ U+1F5FF,即:
"[\\uD83C\\uDF00-\\uD83D\\uDDFF]"
- 增补符号及图形,范围为: U+1F900 ~ U+1F9FF,即:
"[\\uD83E\\uDD00-\\uD83E\\uDDFF]"
- 表情符号一共有80个字符,范围为: U+1F600 ~ U+1F64F,即:
"[\\uD83D\\uDE00-\\uD83D\\uDE4F]"
- 表情符号一共有80个字符,范围为: U+1F600 ~ U+1F64F,即:
"[\\uD83D\\uDE00-\\uD83D\\uDE4F]"
- 交通及地图符号一共有103个字符,范围为: U+1F680 ~ U+1F6FF,即:
"[\\uD83D\\uDE80-\\uD83D\\uDEFF]"
- 杂项符号一共有256个字符,范围为: U+2600 ~ U+26FF 或拼上 U+FE0F,即:
"[\\u2600-\\u26FF]\\FE0F?"
- 装饰符号一共有192个字符,范围为: U+2700 ~ U+27BF 或拼上 U+FE0F,即:
"[\\u2700-\\u27BF]\\FE0F?"
- 键帽符号一共有12个字符,其组成方式为: U+0023、 U+002A 和 U+0030 ~ U+0039 12个键帽基础字符加上 U+FE0F 和 U+20E3,即:
"[\\u0023\\u002A[\\u0030-\\u0039]]\\uFE0F?\\u20E3"
- 还有一些数量较少的emoji表情符号,这里就不一一总结了,大家可以结合上面的文章去查看每个unicode平面的emoji表情的对应的数字。也可以点我查看具体的emoji区间和对应汉字
emoji过滤器实现
前面我们已经了解了emoji表情在utf-8中占四个字节,区间也进行了分类和整理,所以,去判断字符串中是否有emoji表情使用正则或者进行分类判断都是ok的:
"(?:[\uD83C\uDF00-\uD83D\uDDFF]|[\uD83E\uDD00-\uD83E\uDDFF]|[\uD83D\uDE00-\uD83D\uDE4F]|[\uD83D\uDE80-\uD83D\uDEFF]|[\u2600-\u26FF]\uFE0F?|[\u2700-\u27BF]\uFE0F?|\u24C2\uFE0F?|[\uD83C\uDDE6-\uD83C\uDDFF]{1,2}|[\uD83C\uDD70\uD83C\uDD71\uD83C\uDD7E\uD83C\uDD7F\uD83C\uDD8E\uD83C\uDD91-\uD83C\uDD9A]\uFE0F?|[\u0023\u002A\u0030-\u0039]\uFE0F?\u20E3|[\u2194-\u2199\u21A9-\u21AA]\uFE0F?|[\u2B05-\u2B07\u2B1B\u2B1C\u2B50\u2B55]\uFE0F?|[\u2934\u2935]\uFE0F?|[\u3030\u303D]\uFE0F?|[\u3297\u3299]\uFE0F?|[\uD83C\uDE01\uD83C\uDE02\uD83C\uDE1A\uD83C\uDE2F\uD83C\uDE32-\uD83C\uDE3A\uD83C\uDE50\uD83C\uDE51]\uFE0F?|[\u203C\u2049]\uFE0F?|[\u25AA\u25AB\u25B6\u25C0\u25FB-\u25FE]\uFE0F?|[\u00A9\u00AE]\uFE0F?|[\u2122\u2139]\uFE0F?|\uD83C\uDC04\uFE0F?|\uD83C\uDCCF\uFE0F?|[\u231A\u231B\u2328\u23CF\u23E9-\u23F3\u23F8-\u23FA]\uFE0F?)"
网上也有一些相关的简化了的正则,给出一个大概区间,把这些都包含进去就ok,大家也可以看一下,或者针对四个字节的,全部做特殊处理就ok。宁可错杀,也不放过!
总结
至此,我们对于编码格式和unicode又有了一个全新的认识。大家可以多去打印一下各种字符串的字节码的输出和长度的输出,去熟悉编码格式底层的转换和应用。对于我们对于程序的开发,有很好的引导和促进作用。对编码了解了,很多关于I/O,储存,转换的知识点,都能有一个比较立体的图像思维。同时,也能更好理解计算机底层的实现和对于文件,数据的存储。