`
chenzng
  • 浏览: 14101 次
  • 性别: Icon_minigender_1
  • 来自: 成都
社区版块
存档分类
最新评论

Emoji的编码以及常见问题的解决方法

 
阅读更多

原文:https://segmentfault.com/a/1190000007594620

一个Emoji的趣闻

我在 虎嗅上 看过一篇关于Emoji的文章,特别有意思,在这里跟大家分享一下.

里面提到了Emoji是怎么诞生的。

1999年前后,日本一个名叫栗田穰崇的年轻人,和许多直男一样, 给女友发的短信经常会被误解。比如,“知道了”被解读成“生气了”、“不耐烦了”,随后引发冷战。 于是少年栗田想:“如果能在文字里插入一些表情符号来表达感情,大家应该会需要吧!”

原始的Emoji就这么诞生了。

Emoji极大地丰富了我们的生活和通讯交流。Emoji诞生自程序员,但反过来对程序员也造成过一些困扰。

尤其对于面向C端的产品开发者, 用户越来越习惯于输入Emoji, 因此接触Emoji也只会越来越频繁。

Emoji的编码

Emoji字符是Unicode字符集中一部分.

常见的Emoji表情符号在Unicode字符集中的范围和具体的字节映射关系, 可以在 Emoji Unicode Tables 中查看到.

有意思的是, 该表中还给出了同一个Emoji表情在不同系统或应用中的字体(是字体没错, Emoji的样式可通过字体文件改变)。

关于Emoji的最权威资料, 可以在 Unicode® Emoji Charts 上查阅到.

截止我写这篇文章的时刻, Emoji Charts 的最新版本是v3.0, v4.0还只是处于Beta阶段.

题外话补充一点: Unicode是一种字符编码方法,它是由国际组织设计,可以容纳全世界所有语言文字的编码方案。

我们所知道的UTF-8、UTF-16等编码, 是对Unicode的不同实现方式.

如果要深入了解更多关于ASCII、Unicode、UTF-8、gb2312、gbk等编码的相关知识,在这里强烈推荐几篇文章,讲得非常好.

一些特殊的Emoji

在众多Emoji中, 有一些特殊的Emoji 并没有显示的样式, 只是起到了控制的作用。这些控制型的Emoji 与基础Emoji 出现在一起, 可以展示更多的样式.

比如 "变量选择器-15"(VARIATION SELECTOR-15, 简写VS-15): <U+FE0E> , 作用是让基础Emoji 变成更接近文本样式(text-style);

而 "变量选择器-16"(VARIATION SELECTOR-16, 简写VS-16): <U+FE0F> , 作用则是让基础Emoji 变成更接近Emoji样式(emoji-style).

前提是, 如果系统支持的话.

VS-15 和 VS-16 是加在基础Emoji字符的后面, 起到控制作用的.

用一段Python代码来演示该例子:

# -*- coding: utf-8 -*-
# more info to see https://en.wikipedia.org/wiki/Emoji
# 符号分别是上图(截图自wiki)中的符号, 最后再加上一个“狗”的Emoji
sample_list = [u'\u2139', u'\u231B', u'\u26A0', u'\u2712', u'\u2764', u'\U0001F004', u'\U0001F21A', u'\U0001f436', ]

# 输出原样式
for code in sample_list:
    print code,
print
print '-' * 20
# 后面加上VS-15
for code in sample_list:
    print (code + u'\uFE0E'),
print
print '-' * 20
# 后面加上VS-16
for code in sample_list:
    print (code + u'\uFE0F'),

其输出如下图:

另外, 还有起到控制"表示人身体部位的Emoji"的肤色的控制符, 分别是: <U+1F3FB> – <U+1F3FF>共五个, 分别简称为: FITZ-1-2, FITZ-3, FITZ-4, FITZ-5, FITZ-6.

还有一个特殊的控制符: <U+200D> (ZERO WIDTH JOINER, 简写ZWJ), 起到了连接Emoji的作用, 从而将多个Emoji变成一个Emoji来显示. 同样,前提是, 必须系统支持该实现, 否则会忽略.

使用Python代码演示 FITZ-* 和 ZWJ :

# -*- coding: utf-8 -*-
# more info to see https://en.wikipedia.org/wiki/Emoji

# man_list 分别是: 男孩  女孩  男人  女人
man_list = [u'\U0001F466', u'\U0001F467', u'\U0001F468', u'\U0001F469']
# skin_color_list 分别是: 空字符串,表示默认  白种人 -->(不断加深肤色)  黑种人
skin_color_list = ['', u'\U0001F3FB', u'\U0001F3FC', u'\U0001F3FD', u'\U0001F3FE', u'\U0001F3FF', ]
for man in man_list:
    for color in skin_color_list:
        print (man + color),
    print
    print '-' * 20

# Emoji的连接符<U+200D>  (英文名为: ZERO WIDTH JOINER, 简写ZWJ )
# 如果系统支持: 连接(男人 + ZWJ + 女人 + ZWJ + 女孩)
print u'\U0001F468' + u'\u200D' + u'\U0001F469' + u'\u200D' + u'\U0001F467'
# 如果系统不支持: 连接(狗 + ZWJ + 猫 + ZWJ + 老鼠)
print u'\U0001f436' + u'\u200D' + u'\U0001f431' + u'\u200D' + u'\U0001f42d'

其输出如下图:

以上内容参考自 维基百科

对Emoji 的介绍到该小节结束, 下面内容是一些关于实际中可能遇到的技术问题的解决方法.

MySQL存储Emoji

使用MySQL存储Emoji, 只需要数据表的字符集为 utf8mb4 即可, 即 CHARSET=utf8mb4 .

如果想要知道你的MySQL数据库是否支持 utf8mb4 编码, 可通过 show charset; 输出当前安装的MySQL所支持的所有字符集, 查看输出中是否包含有 utf8mb4 .

另外, 有一些比较老的业务, 可能一开始设计时没考虑到需要支持Emoji, 那就需要修改数据库或数据表的字符集.

查看MySQL说支持的所有字符集
mysql> show charset;

查看某张表当前的字符集
mysql> show create table <table_name>;

创建默认字符集为utf8mb4的数据库.在该数据库中,如果创建表时是不指明字符集,则默认utf8mb4.
mysql> create database default charset utf8mb4;

创建字符集为utf8mb4的表, 数据库的默认字符集非utf8mb4也没问题.
mysql> create table `<table_name>` (Column定义, Column定义, ...) DEFAULT CHARSET=utf8mb4;

修改已存在的数据库的字符集
mysql> alter database <db_name> default charset = utf8mb4;

修改已存在的表的字符集
mysql> alter table <table_name> default charset = utf8mb4;

如果遇到需要大量修改MySQL字符集的重复工作, 这里介绍一个生成"批量修改字符集语句"的方法, 对输出复制粘贴即可.

使用 mysql -u<your_user_name> -p<your_password> -s --disable-column-names 登录MySQL数据库.

选项 -s 是 --silence 的意思, 将不会输出绘制表格的字符; --disable-column-names 表示不要输出段名.

mysql> SELECT CONCAT('alter TABLE ',TABLE_NAME,' default charset utf8mb4;') FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA='<db_name>' AND TABLE_TYPE='BASE TABLE';

举例查看输出的内容(假设数据库名为 test_db ):

mysql> SELECT CONCAT('alter TABLE ',TABLE_NAME,' default charset utf8mb4;') FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA='test_db' AND TABLE_TYPE='BASE TABLE';
alter TABLE test_t default charset utf8mb4;
alter TABLE test_t2 default charset utf8mb4;
alter TABLE test_t3 default charset utf8mb4;

使用正则表达式替换/找出字符串中的Emoji

很可惜, Emoji的范围并没有明确的定义. 正如上面提到了, Emoji Charts目前最新版本是v3.0, 未来Emoji的范围还会不断扩大.

并且, Emoji 在Unicode的分配中, 并不是连续的区间.

所以, 在这里我只能给出一个可行的区间, 涵盖了基本常见的Emoji, 而且区间中还会包含一些未定义的字符(可能在某些系统会有定义,但是在另外的系统中并没有定义, 毕竟Emoji是商业的产物)。

该匹配规则区间参考了 emoji-data.txt 和 Unicode® Technical Report #51 , 如下:

<U+1F300> - <U+1F5FF>      # symbols & pictographs
<U+1F600> - <U+1F64F>      # emoticons
<U+1F680> - <U+1F6FF>      # transport & map symbols
<U+2600>  - <U+2B55>       # other

下面使用Python代码来演示如何使用正则表达式替换(或找出)字符串中的Emoji:

# -*- coding: utf-8 -*-
import re
try:
    # Wide UCS-4 build
    myre = re.compile(u'['
        u'\U0001F300-\U0001F64F'
        u'\U0001F680-\U0001F6FF'
        u'\u2600-\u2B55]+',
        re.UNICODE)
except re.error:
    # Narrow UCS-2 build
    myre = re.compile(u'('
        u'\ud83c[\udf00-\udfff]|'
        u'\ud83d[\udc00-\ude4f\ude80-\udeff]|'
        u'[\u2600-\u2B55])+',
        re.UNICODE)

sss = u'I have a dog \U0001f436 . You have a cat \U0001f431 ! I smile \U0001f601 to you!'
print myre.sub('[Emoji]', sss)  # 替换字符串中的Emoji
print myre.findall(sss)         # 找出字符串中的Emoji

输出如下:

I have a dog [Emoji] . You have a cat [Emoji] ! I smile [Emoji] to you!
[u'\U0001f436', u'\U0001f431', u'\U0001f601']

上面例子中, 之所以使用 try...except... 来处理代码, 是考虑到 UCS-2 (Narrow UCS-2 build) 和 UCS-4 (Wide UCS-4 build) 的区别.

该Demo例子参考了 stackoverflow 上的精彩回答, 解答了我对此的困惑。

关于UCS-2和UCS-4的区别, 在上面提到的扩展阅读 程序员趣味读物:谈谈Unicode编码 中有提到, 值得一看.

本文中使用到的示例代码,可以在 我的github上 下载到.

Emoji可能遇到的字符串截断问题

在Python、JavaScript 这类语言中, 对Unicode的"汉"字取长度时,长度为1.

Python为例:

>>>len(u'汉')
1

但是对于大部分的Emoji(并非全部), 取长度则为2. 比如 <U+1f436> (Emoji表情是一只萌萌的狗)

Python:

>>>len(u'\U0001f436')
2

那么, 这就存在一个隐患, 在对字符串进行截断时可能从中间截断, 导致字符显示乱码, 甚至引发报错.

比如继续使用上面例子:

>>>u'这是一只可爱的狗狗\U0001f436'.__len__()
11
>>>u'这是一只可爱的狗狗\U0001f436'[0:10]
这是一只可爱的狗狗???

对字符串进行截断,这在实际的开发过程中是非常常见的需求,而且字符串往往可能是用户高度自由的输入内容, 那么包含Emoji的可能性其实是很高的.

一个具体的场景就是: 你们开发了一款社交APP, 允许用户保存文字记录, 然后在应用的某个地方, 又需要显示这些文字记录的摘要,摘要只显示100个字符, 其他省略。

这就会对一串"未知的字符串"进行前100个字符的裁剪。

解决方案也有多种:

  • 全文进行正则匹配, 去掉大部分Emoji, 但是文本长度过长的情况消耗太大, 不值得.

  • 先截取前200个字符, 匹配去掉Emoji再截取100个字符. 貌似可行. 但如果极端条件下前200个字符都是Emoji怎么办? 管他的.

  • 运用上面提到的扩展阅读: 阮一峰博客 中提到的UTF-8的编码规则, 对截断后字符串的最后字符进行检查, 发现是截断的字符即进行剔除。该方案可行, 不过你需要自己去实现了。

  • 允许一定概率出现乱码, 乱码就乱码吧,谁叫用户要这样输入的,概率不高, 不会有人发现的。再者, 不影响主要体验。别告诉产品经理就行。将更多精力放在避免其他bug上吧。

分享到:
评论

相关推荐

    emoji图片和编码表

    在IT行业中,emoji表情符号已经成为了我们日常沟通中不可或缺的一部分,尤其在文本交流、社交媒体和移动应用...同时,拥有详细的emoji编码表可以帮助解决字符显示问题,优化用户体验,从而提升应用的质量和用户满意度。

    emoji 表情图片解决方法

    这样的工具可能包括对emoji编码的解析、图片资源的打包和优化等功能。 此外,对于一些高级需求,比如在移动应用中,开发者可能需要处理emoji的兼容性问题。例如,iOS和Android设备对emoji的支持程度不同,需要适配...

    emoji转换文件,良心文件啊,php版本

    此压缩包提供的类库就是为了解决这些问题,它能够将emoji编码统一处理,确保在各种场景下都能正确显示。 描述中提到的"实际操作demo"部分,意味着这个类库附带了示例代码,这有助于开发者快速理解和使用。通过查看...

    火山安卓Emoji表情编码转换案例.rar

    在Android开发中,Emoji表情的编码转换是一个常见的需求,特别是在处理用户输入或者显示文本时,因为不同的设备和系统可能对Emoji的支持方式有所不同。这个“火山安卓Emoji表情编码转换案例”提供了一个具体的解决...

    emoji表情web处理

    可以使用类似于前端的方法,如转换编码或使用特定的库来处理emoji。例如,Node.js环境中可以使用`node-emoji`库来解析和渲染emoji。 在实际应用中,可能还需要考虑到性能和用户体验,避免过多的DOM操作或重绘,以及...

    emoji-java-master

    "emoji-java"库是为了解决这些问题而设计的,它提供了一系列方便的方法,帮助开发者轻松地在Java程序中处理Emoji。这个库支持常见的Unicode Emoji,并且可以方便地进行解析、编码、解码和搜索等操作。 1. **核心...

    java解析emoji表情存入oracle,并正常使用

    每个emoji由两个UTF-16编码组成,可以使用Java的`Character.toChars()`方法将其转换为字节数组,然后存入数据库的BLOB或CLOB字段。 在给定的文件列表中,`emoji-java-4.0.0.jar`是一个用于处理emoji的Java库,它...

    Unity开发对Emoji表情包图文混排进行处理显示(支持大多数表情)

    这些库可能已经解决了许多常见的问题,减少了开发工作量。 7. **性能考虑**:处理和渲染大量Emoji可能会对性能产生影响,特别是对于移动设备。优化点可能包括延迟加载、异步处理、减少不必要的更新,以及使用纹理 ...

    微信开发之emoji表情在网页上显示,很好用

    2. CSS字体图标库:另一种常见方法是使用预设的CSS图标库,如Font Awesome、Twitter的Twemoji等。这些库将大量emoji编码为特定字体中的字符,通过设置CSS的`content`属性和`font-family`,可以轻松插入表情。 3. ...

    emoji表情转换 Usc2转Html 10_16

    在实际应用中,开发者或用户可能会遇到这样一个问题:在某些系统或平台上,emoji可能无法直接显示,这时就需要通过编码转换来解决。例如,将USC2编码的emoji转换为HTML实体,使得浏览器能够识别并渲染出来。这是因为...

    emoji表情插件

    4. **测试和调试**:确保在不同的设备和浏览器上都能正常工作,解决可能出现的兼容性问题。 通过以上步骤,你就可以在自己的Web应用中成功集成并使用emoji表情插件,提升用户的交互体验。不过,要注意持续关注emoji...

    3种方法轻松处理php开发中emoji表情的问题

    在PHP开发过程中,尤其是涉及到与社交媒体或通讯应用的交互时,遇到emoji表情是一个常见的问题。微信作为一款广泛使用的社交平台,允许用户使用emoji作为昵称,但这些表情在存储到使用UTF8字符集的MySQL数据库时会...

    ios-图文混排之解析Emoji.zip

    "ios-图文混排之解析Emoji.zip"这个资源包提供了解决这一问题的解决方案,它包含了自定义的解析工具类,能够将带有Emoji的文本消息解析为富文本,以便在UILabel和UITextView中正确地显示。 首先,我们要理解的是,...

    emoji表情本地JSON文件

    "emoji表情本地JSON文件"是为了解决这个问题而设计的一种资源库,它提供了丰富的表情符号供用户在网页或应用中使用。这个资源库包含了167个常用的表情,每个表情都附带了名称、分类标签以及UTF-16编码,使得前端...

    Android使用Emoji表情Demo

    为了解决这个问题,你可以使用一些开源库,如`EmojiCompat`,它提供了对旧版Android的Emoji兼容性支持。`EmojiCompat`库会动态加载并替换不支持的Emoji,使其能够在设备上正常显示。 5. **布局适配**:Emoji通常比...

    Emoji转换工具,便于各种类型的客户端生成的Emoji字符串转换成另外一种格式

    在IT行业中,尤其是在开发跨平台或跨设备的应用时,Emoji的兼容性和一致性是一个常见的问题。不同的操作系统、浏览器或客户端可能对同一Emoji表情符号有不同的编码方式,导致在不同环境下的显示不一致。为了解决这个...

    MySQL无法存储Emoji表情问题的解决方法分析

    因此,要解决MySQL无法存储Emoji表情的问题,需要将数据库、表以及字段的字符集都调整为utf8mb4。 首先,需要修改MySQL配置文件my.ini,在[mysql]和[mysqld]部分设置正确的字符集。具体操作如下: 1. 找到MySQL...

    android emoji表情

    为解决这个问题,你可以使用第三方库,如Android-Emoji-Compat或EmojiOne,它们提供了广泛的emoji支持和统一的显示效果。这些库通常会包含一个自定义的Typeface,可以替换默认的字体,从而确保在所有设备上都能正常...

Global site tag (gtag.js) - Google Analytics