Unicode 字符编码组合

本贴最后更新于 811 天前,其中的信息可能已经事过景迁

起因

最近在开发的时候有一个需求:因为空间原因比较小等原因某些位置展示不下,需要进行截断展示,发现国旗图标(🇸🇪)按照这个格式解析不出来,具体排查发现这个国旗图标对应的 UTF-8 二进制格式是:

11110000
10011111
10000111
10111000
11110000
10011111
10000111
10101010

发现并不满足标准的 UTF-8 格式,而是两个 UTF-8 字符编码拼接起来的。

初步排查

通常来讲提到的 UTF-8 都是基础的基础格式:https://www.rfc-editor.org/rfc/rfc3629#page-5

根据查阅了相关资料及文章后发现国旗图标是按照一定规则由 2 个字符组合出来的,大致代码如下:

OFFSET = 0x1F1A5
def get_country_flag(code):
    return chr(OFFSET + ord(str.upper(code[0]))) + chr(OFFSET + ord(str.upper(code[1])))

其参数为国家代码,如 CN,US 等,返回值为对应国家国旗的 emoji 图标,就是说国旗编码是由两个 Unicode 字符组合而成的,那么解决办法就是如果当前字符是在 0x1F1E60x1F1FF 之间,判断下一个字符是否也在这个范围之间,如果在的话,那么就认为这两个共同组成一个显示的文字。

新的问题

处理完国旗问题以后,同事又发了几个新的字符:👩🏻👩🏼👩🏽👩🏾👩🏿,拆解这几个字符会发现和国旗一样是由两个 Unicode 编码组成的,查阅相关资料后发现 emoji 实际上是有"皮肤"的概念的,即正常图标 + 颜色修饰,修饰字符的范围为 0x1F3FB-0x1F3FF

紧接着同事又发了下面这个东西:



Z͑ͫ̓ͪ̂ͫ̽͏̴̙̤̞͉͚̯̞̠͍A̴̵̜̰͔ͫ͗͢L̠ͨͧͩ͘G̴̻͈͍͔̹̑͗̎̅͛́Ǫ̵̹̻̝̳͂̌̌͘!͖̬̰̙̗̿̋ͥͥ̂ͣ̐́́͜͞


这个东西实际上是对 ZALGO! 的这五个字符的修饰,就是每个字母后面都跟着大量的用于修饰前面字符的编码。

查阅相关资料后发现这些组合字符的范围分为几段:0x0300 - 0x036F0x1DC0 - 0x1DFF0x20D0 - 0x20FF0xFE20 - 0xFE2F,这些编码一定是依赖于前一个字符存在而存在的。

后来找到了这样两个网址:

https://www.unicode.org/Public/emoji/14.0/emoji-sequences.txt

https://www.unicode.org/Public/emoji/14.0/emoji-zwj-sequences.txt

这里面是 Unicode14.0 的基础 emoji 和组合 emoji 图标,在这里面又发现了几个之前没注意到的编码:0x200D0xFE0F

0x200D 是用于将前面一个编码和后面一个编码“粘起来”的编码,0x200D 前后共通组成一个用于显示的字符。

0xFE0F 是用于修饰前面一个编码的(根据相关文档介绍, 0xFE00-0xFE0F 均是,但是常见的只有 0xFE0E0xFE0F),具体用处还没太搞清楚。

此外,还有除了常规两个编码拼接起来的国旗以外,还有三个 Unicode 5.0 加入的由七个编码组成的特殊国旗:🏴󠁧󠁢󠁥󠁮󠁧󠁿、🏴󠁧󠁢󠁳󠁣󠁴󠁿、🏴󠁧󠁢󠁷󠁬󠁳󠁿,这三个还需要特殊处理。

在查找问题的过程中还发现了这样一个网站:https://www.compart.com/en/unicode/,可以很方便的查询单个 Unicode 编码的用处。

总结

目前很多程序使用的都是 UTF-8 或者 UTF-16 编码,需要先拿到每个字符的 Unicode 编号,这个在大部分语言中都是内置提供的,不需要特殊处理,直接使用即可。

  1. 从前往后读取的过程中,需要判断当前字符是否是国旗编码所在范围内,如果在的话需要判断是否能与下一个(普通国旗)或多个字符(🏴󠁧󠁢󠁥󠁮󠁧󠁿🏴󠁧󠁢󠁳󠁣󠁴󠁿🏴󠁧󠁢󠁷󠁬󠁳󠁿)组成国旗,如果能的话需要和前一个合并处理。
  2. 判断下一个字符是否是修饰编码或者组合编码(如 0xFE0F0x0300 等),如果是的话那么也需要合并到前一个处理。
  3. 上述判断完成后还需要判断下一个字符是否是 0x200D,如果是的话,那么需要再向下读取前至少 1 个,具体数量重复上述 1-2 步骤进行判断。

综合以上信息可以解决目前遇到的大部分的 Unicode 字符截断展示的问题,但这里面有两个问题:

  1. 目前接触到的类型还比较少,可能还有尚没有接触到的编码,遇到了还需要进行补充。
  2. Unicode 版本是一直在更新的,如果新版本发布了可能还需要跟进相关的适配。

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...