【原创】经验分享:一个小小emoji尽然牵扯出来这么多东西?

本文讲述了在处理包含emoji的字符串时遇到的问题,如中文字符判断和emoji截取异常。介绍了utf8mb4、ASCII码、Unicode、UTF-16等相关概念,并详细分析了emoji在UTF-16编码下导致的截取问题及其解决方案。通过实例代码展示了如何正确处理emoji,同时提及了Unicode字符的捐赠机制。
摘要由CSDN通过智能技术生成

前言

之前也分享过很多工作中踩坑的经验:

  1. 一个线上问题的思考:Eureka注册中心集群如何实现客户端请求负载及故障转移?
  2. 【原创】经验分享:一个Content-Length引发的血案(almost…)

今天再来分享工作中一个真实的案例:

商品评价列表页,显示每条用户的评价详情,为了保护用户隐私,要求显示用户昵称时只能显示第一位和最后一位,其他的用※代替。

例如输入:🐳🐳🐠,输出:🐳***🐠

看似一个平淡无奇的需求,我也没有太在意。服务端将用户的评论信息存储到db中,评价列表接口就是将数据库中该商品的评论信息展示出来,特殊处理下评论人的昵称就可以了。

但是!! 测试同学发现用户昵称包含emoji表情时就会出问题,切割的数据会有问号显示!!

模拟的示例代码如下:

字符串截取.png

输出:

输出.png

看到这个输出,我真的是一脸懵逼,这完全不是我想要的结果呀!!!

黑人问号.png

这三个鱼可算是难倒我了,难道只能给测试说 emoji太特殊 不予处理?然后撒个娇蒙混过关?

思考了良久,我还是决定要正视这个问题并解决掉它!(毕竟我还是那个不畏困难的小机灵鬼🤔)

问题不大.png

PS:本文很大程度是受到之前公司一位同事unicode分享的启发,在这里向我的这位老师致敬!下面的内容会一步步分析这个问题的产生以及最终的解决方案。

概念常识

要解决这些问题,就必须要铺垫一些基础知识,大家等不及看解决方案 可以拉到文章最后的代码示例。

utf8mb4

一般我们在数据库创建表时都会默认使用这种编码格式:

utf8mb4编码.png

相信大家对这个编码格式都不陌生吧,当我们想存储emoji数据到数据库中,那么数据库的格式就需要指定为utf8mb4了,要不然存储就会报错了。所以在很多公司的db规范中,数据库默认编码必须为utf8mb4

emoji保存报错.png

但是大家有没有过这样的疑惑,为何utf8不行而utf8mb4就行?这里面到底有什么弯弯道道

这里面涉及到unicode相关知识,我们下面会提到,大家继续看。

mysql 5.5 之前,utf8编码只支持1-3个字节,从mysql 5.5开始,可支持4个字节UTF编码utf8mb4,一个字符最多能有4字节,所以能支持更多的字符集。

emoji长度.png

这个表格中包含了所有的 emoji 以及它所对应的 unicode编码,同时也有对应的 utf-8编码的实现。

从图中也可以看出 emoji 表情用 utf-8 表示时会占用 4个字节,这也就是为什么数据库用utf8无法存储emoji表情的原因了。

同样我们也可以在java代码中看看emoji占用几个字节长度:

emoji长度.png

我们也可以看到String.getBytes(),默认是utf-8编码的:

String.getBytes编码格式.png

ASCII码

上面介绍utf8mb4时有提过unicode,介绍它之前我们也需要先提一嘴我们的老朋友:ASCII

ASCII(American Standard Code for Information Interchange,美国信息交换标准代码)是基于拉丁字母的一套电脑编码系统。它主要用于显示现代英语。

这样我们就可以使用一个字节来表示现代英文,看起来非常不错,部分数据对应关系如下:

ASCII码.png

但这个只能显示的代表拉丁文,这显然是远远不够的。

Unicode

显而易见,计算机的发展并不是只支持英文一种语言的,ASCII的局限在于只能显示26个基本拉丁字母、阿拉伯数字和英式标点符号,因此只能用于显示现代美国英语。

这时如果能有一种包含了世界上所有的文字的字符集,每一个地区的文字都在这个字符集中有唯一的二进制表示,这样便不会出现乱码问题了。所以Unicode也应运而生了。

概念

Unicode,中文又称万国码、国际码、统一码、单一码,是计算机科学领域里的一项业界标准。它对世界上大部分的文字系统进行了整理、编码,使得电脑可以用更为简单的方式来呈现和处理文字。

平面

Unicode 首先承认了 ASCII 占用 0-127 整数资源的合法性,之后又一次占用了 128-65535 的整数资源,有了这么多的整数资源,我们就可以把世界各种文字的每一种字符分配一个整数来表示了。

之后,Unicode 联盟发现 65536 个整数也不够分配的,于是就索性一次性又把之后的 16 个 65536 的数字即 65536-1114111 的整数资源给占了,然后把多占的 16 个 65536 的段分别命名为 16 个平面,加上原来的 0-65535 平面Unicode 总共有 17 个平面

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值