UTF-8编码可显示字符的最大代码点数量是多少?
UTF-8可显示字符的最大代码点数量问题
问题背景
在向数据库插入表情符号时,我们遇到了与UTF-8编码相关的异常:
- 👍(仅1个代码点
U+1F44D)可正常插入 - 🌶(由
U+1F336(Hot Pepper)和U+FE0F(变体选择符-16)2个代码点组成)插入失败
将数据库存储宽度调整为2后,🌶的插入问题解决,但新的问题出现:
- 键帽表情(如1️⃣)由3个代码点组成:
U+31(数字1)、U+FE0F、U+20E3(组合封闭键帽) - 再次调整宽度到4后,🤦🏼♂️(包含5个代码点:
U+1F926(捂脸)、U+1F3FC(菲茨帕特里克肤色修饰符-3)、U+200D(零宽连接符)、U+2642(男性符号)、U+FE0F)仍无法插入 - 进一步测试发现,英格兰国旗表情🏴包含7个代码点:
U+1F3F4:挥舞的黑旗U+E0067:标签小写字母GU+E0062:标签小写字母BU+E0065:标签小写字母EU+E006E:标签小写字母NU+E0067:标签小写字母GU+E007F:取消标签
核心问题
UTF-8编码的可显示字符最多可包含多少个代码点?是否存在代码点数量超过7个的表情符号或其他UTF-8字符?
注:本问题与另外两个常见问题不同:
- 不同于《What is the maximum number of bytes for a UTF-8 encoded character?》:后者询问单个UTF-8代码点的最大字节数(答案为4)
- 不同于《Does Unicode have a defined maximum number of code points?》:后者关注Unicode定义的代码点总数,而非单个可显示字符的连续代码点数量
解答
1. 术语说明
Unicode中,这类由多个代码点组合而成的可显示字符被称为grapheme簇(Grapheme Cluster),它是用户感知到的单个“字符”,但底层由多个代码点构成。
2. 最大代码点数量
Unicode标准并未定义grapheme簇的代码点数量上限,实际存在的表情符号中,已有大量超过7个代码点的例子:
最典型的是多成员且带有不同肤色修饰符的家庭组合表情,例如👨🏼👩🏻👧🏽👦🏾,它的代码点组成多达11个:
U+1F468:成年男性U+1F3FC:菲茨帕特里克肤色修饰符-3U+200D:零宽连接符U+1F469:成年女性U+1F3FB:菲茨帕特里克肤色修饰符-1U+200D:零宽连接符U+1F467:女孩U+1F3FD:菲茨帕特里克肤色修饰符-4U+200D:零宽连接符U+1F466:男孩U+1F3FE:菲茨帕特里克肤色修饰符-5
此外,理论上还可以通过零宽连接符组合更多角色(如添加更多家庭成员),生成代码点数量更多的grapheme簇,只要系统支持渲染,就能作为单个可显示字符存在。
3. 数据库存储建议
由于grapheme簇的代码点数量没有上限,通过调整存储宽度来适配的方式不可持续。建议:
- 使用支持完整UTF-8的字段类型,如MySQL的
utf8mb4编码 - 优先选择不限制长度的文本类型(如
TEXT),或按字节数而非代码点数量配置字段长度 - 若必须限制长度,可在业务层对grapheme簇数量做限制,而非代码点数量
内容的提问来源于stack exchange,提问作者jgawrych
相关产品推荐
相关产品推荐

