本文主要是介绍android emoji吏上最全的详解,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
如果没有时间看这么多历史介绍知识点,请直接跳到 第五小节:《java删除字符串中的所有emoji字符》
一、emoji简介
简介的内容摘自 wiki 百科对emoji的描述。这里把基本概念列举出来,方便内部世界的童鞋查阅。
1. 概念
- emoji(英语:emoji,日语:絵文字/えもじ emoji),是使用在网页和聊天中的形意符号,最初是日本在无线通信中所使用的视觉情感符号(图画文字)。表情意指面部表情,图标则是图形标志的意思,可用来代表多种表情,如笑脸表示笑、蛋糕表示食物等。在中国大陆,emoji通常叫做“小黄脸”[6],或者直称emoji[7]。在台湾LINE软件中,emoji又被叫做“表情贴”。
2.历史
- 第一个表情符号是由栗田穰崇于1998年或1999年创造,他当时隶属于NTT DoCoMo公司i-mode移动互联网平台的团队。第一套表情符号包括172个12×12像素的图标,设计初衷是作为i-mode消息功能的一部分帮助促进电子通讯,并作为区别于其他业务的特色功能。 然而在1997年,Nicolas Loufrani注意到,ASCII表情符号在移动技术中的使用正在增加,他开始尝试动画效果的笑脸表情,目的是使用纯标点符号设计一套与现有ASCII表情对应的彩色图标,以促进其在数位领域的使用。Loufrani由此创造了第一套图形化表情,并编译了在线表情符号词典, 将这些符号分成不同类别,包括:经典类、情绪类、旗标类、庆贺类、娱乐类、体育类、天气类、动物类、饮食类、民族类、职业类、行星类、星座类、婴儿类等,这些设计最初于1997年在美国版权局注册,随后全套图标于1998年以.gif格式文件在网络上发布,成为科技行业中使用的第一套图形化表情符号。2000年,Loufrani创建的表情目录开始提供下载,用户开始可从互联网上透过smileydictionary.com为手机下载Loufrani创建的表情目录,该目录编译了超过1000个笑脸图形表情符号及其ASCII版本。该目录在2002年由Marabout以书籍形式出版,名称为Dico Smileys。2001年,表情符号公司Smiley Company 开始向各家电信公司的手机提供Loufrani图形表情符号的授权下载,这些公司包括诺基亚、摩托罗拉、三星、SFR(沃达丰)和SkyTelemedia。其中,“😂”(中文:喜极而泣的表情,英语:Face with Tears of Joy,Unicode码位:U+1F602[8][9])被《牛津词典》评选为2015年度词汇。
3.各版本unicode分配的emoji码位
Unicode版本历史 | emoji码位个数 (括号内的数字表示相比于一上版本增加的个数) |
---|---|
1.0.0 | 78 (+78) |
3.0 | 80 (+2) |
3.2 | 88 (+8) |
4.0 | 96 (+8) |
4.1 | 111 (+15) |
5.1 | 115 (+4) |
5.2 | 142 (+27) |
6.0 | 858 (+716) |
6.1 | 871 (+13) |
7.0 | 975 (+104) |
8.0 | 1,016 (+41) |
9.0 | 1,088 (+72) |
10.0 | 1,144 (+56) |
更多unicode历史片的变化,请查阅 https://zh.wikipedia.org/wiki/Unicode#%E6%A8%99%E6%BA%96。 unicode的最新版本为 2019年5月 发布的12.1 版本。
注:这些是独立Unicode符号计数。许多emoji其实是两个或以上的代码按顺序组成的。emoji的零宽连接符在Unicode 6.0中首次被定义。因此各版本的emoji符号总数是大于上表的统计的
前序:为了文章表述具体,以下将肉眼可识别的符号定义为“emoji符号”,如👦;其在机器内的unicdoe编码称为"emoji编码",如“U+1F466”。 emoji编码也有很多格式,在unicode中形如“U+1F466”,用UTF‑16 LE表示时形如3D D8 66 DC,常用的替代格式形如"\uD83D\uDC66"。如何将普通的unicode转换成utf-8、utf-16,下文有介绍。
二、特殊的emoji符号
1. 肤色符号
Unicode 8.0中加入了5个修饰符,用来调节人形表情的肤色。这些叫做emoji菲茨帕特里克修饰符(EMOJI MODIFIER FITZPATRICK)类型-1-2、-3、-4、-5和-6(U+1F3FB ~ U+1F3FF):🏻 🏼 🏽 🏾 🏿。对应了菲茨帕特里克度量对人类肤色的分类。没有后缀肤色代码的emoji会显示非真实的通用肤色例如亮黄色(█)、蓝色(█)或灰色(█)。非人形表情则不受修饰符影响。在Unicode 9.0中菲茨帕特里克修饰符可以和86个人形emoji一起使用。
- 菲茨帕特里克修饰符使用示例
代码位 | 默认 | 菲茨-1-2 | 菲茨-3 | 菲茨-4 | 菲茨-5 | 菲茨-6 |
---|---|---|---|---|---|---|
U+1F466: 男孩 | 👦 | 👦🏻 | 👦🏼 | 👦🏽 | 👦🏾 | 👦🏿 |
U+1F467: 女孩 | 👧 | 👧🏻 | 👧🏼 | 👧🏽 | 👧🏾 | 👧🏿 |
U+1F468: 男人 | 👨 | 👨🏻 | 👨🏼 | 👨🏽 | 👨🏾 | 👨🏿 |
U+1F469: 女人 | 👩 | 👩🏻 | 👩🏼 | 👩🏽 | 👩🏾 | 👩🏿 |
- 示例解析:
"U+1F466"这个unicdoe表示默认的男孩emoji,在其末尾追加"U+1F3FB"来指定其肤色为“菲茨-1-2”级。查看某个unicdoe编码对应符号可以使用这个网页 unicode编码与相对应符号查阅。 这个网页工具的使用方法可以此文章末尾有详细介绍。
U+1F466 | U+1F3FB | U+1F466 U+1F3FB |
---|---|---|
反例:"\uD83D\uDC4B\uD83C\uDFFB"表示"👋🏻",即白色的手掌。其实组成为 前半段"\uD83D\uDC4B" 表示默认手掌"👋",后半段"\uD83C\uDFFB"表示白色肤色"🏻"。 组合起来为“白色手掌”。
2. 零宽连接符
- 零宽连接符的unicode编码为"U+200D",它可以来将两个emoji连起来,使其看起来像是一个emoji。
- 例如U+1F468男人👨、U+200D ZWJ、U+1F469女人👩、U+200D ZWJ、U+1F467女孩(👧)在系统支持的情况下会显示为一个男人一个女人和一个女孩组成的家庭emoji(👨👩👧),组合后的完整unicode为"U+1F468U+200DU+1F469U+200DU+1F467",而不支持的系统则会顺序显示这三个emoji(👨👩👧)。
分解示意图如下:
三、unicode码表中的emoji区块
参考资料1:这个网址详细收录了所有emoji unicode: https://apps.timwhitlock.info/emoji/tables/unicode。 并且提供了unicode码表.txt文件,以供下载。 另外还收录的emoji进行了分类,非常方便开发者直接应用到自己的 app 中。
参考资料2:For a fuller and more up-to-date list of Emoji codepoints, see Unicode’s Full Emoji List. 这个地址是unicode官方网站给出的所有 emoji,应该是全世界全权威的统计。 这里还列举了unicode中所有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。
- | - | - |
---|---|---|
四、unicode 与utf-8、utf-16的关系
4.1 现有的问题
- Unicode 只是一个符号集,它只规定了符号的二进制代码,却没有规定这个二进制代码应该如何存储。
- 比如,汉字严的 Unicode 是十六进制数4E25,转换成二进制数足足有15位(100111000100101),也就是说,这个符号的表示至少需要2个字节。表示其他更大的符号,可能需要3个字节或者4个字节,甚至更多。
- 这里就有两个严重的问题,第一个问题是,如何才能区别 Unicode 和 ASCII ?计算机怎么知道三个字节表示一个符号,而不是分别表示三个符号呢?第二个问题是,我们已经知道,英文字母只用一个字节表示就够了,如果 Unicode 统一规定,每个符号用三个或四个字节表示,那么每个英文字母前都必然有二到三个字节是0,这对于存储来说是极大的浪费,文本文件的大小会因此大出二三倍,这是无法接受的。
4.2 它们造成的结果:
- 1)出现了 Unicode 的多种存储方式,也就是说有许多种不同的二进制格式,可以用来表示 Unicode。
- 2)Unicode 在很长一段时间内无法推广,直到互联网的出现。
4.3 ASCII
计算机内部,所有信息最终都是一个二进制值。每一个二进制位(bit)有0和1两种状态,因此八个二进制位就可以组合出256种状态,这被称为一个字节(byte)。也就是说,一个字节一共可以用来表示256种不同的状态,每一个状态对应一个符号,就是256个符号,从00000000到11111111。
上个世纪60年代,美国制定了一套字符编码,对英语字符与二进制位之间的关系,做了统一规定。这被称为 ASCII 码,一直沿用至今。
ASCII 码一共规定了128个字符的编码,比如空格SPACE是32(二进制00100000),大写的字母A是65(二进制01000001)。这128个符号(包括32个不能打印出来的控制符号),只占用了一个字节的后面7位,最前面的一位统一规定为0。
4.4 UTF-8简介
互联网的普及,强烈要求出现一种统一的编码方式。UTF-8 就是在互联网上使用最广的一种 Unicode 的实现方式。其他实现方式还包括 UTF-16(字符用两个字节或四个字节表示)和 UTF-32(字符用四个字节表示),不过在互联网上基本不用。重复一遍,这里的关系是,UTF-8 是 Unicode 的实现方式之一。
UTF-8 最大的一个特点,就是它是一种变长的编码方式。它可以使用1~4个字节表示一个符号,根据不同的符号而变化字节长度。
4.5 UTF-8编码规则
完整详细的编码规则可以参考 wiki百科对utf-8的介绍: https://zh.wikipedia.org/wiki/UTF-8
这里总结核心要点,UTF-8 的编码规则很简单,只有二条:
1)对于单字节的符号,字节的第一位设为0,后面7位为这个符号的 Unicode 码。因此对于英语字母,UTF-8 编码和 ASCII 码是相同的。
2)对于n字节的符号(n > 1),第一个字节的前n位都设为1,第n + 1位设为0,后面字节的前两位一律设为10。剩下的没有提及的二进制位,全部为这个符号的 Unicode 码。
下表总结了编码规则,字母x表示可用编码的位。
跟据上表,解读 UTF-8 编码非常简单。如果一个字节的第一位是0,则这个字节单独就是一个字符;如果第一位是1,则连续有多少个1,就表示当前字符占用多少个字节。
下面,还是以汉字严为例,演示如何实现 UTF-8 编码。
严的 Unicode 是4E25(100111000100101),根据上表,可以发现4E25处在第三行的范围内(0000 0800 - 0000 FFFF),因此严的 UTF-8 编码需要三个字节,即格式是1110xxxx 10xxxxxx 10xxxxxx。然后,从严的最后一个二进制位开始,依次从后向前填入格式中的x,多出的位补0。这样就得到了,严的 UTF-8 编码是11100100 10111000 10100101,转换成十六进制就是E4B8A5
4.6 UTF-16编码规则
完整详细的编码规则可以参考 wiki百科对utf-8的介绍: https://zh.wikipedia.org/wiki/UTF-16
4.7 Little endian 和 Big endian
上一节已经提到,UCS-2 格式可以存储 Unicode 码(码点不超过0xFFFF)。以汉字严为例,Unicode 码是4E25,需要用两个字节存储,一个字节是4E,另一个字节是25。存储的时候,4E在前,25在后,这就是 Big endian 方式;25在前,4E在后,这是 Little endian 方式。
这两个古怪的名称来自英国作家斯威夫特的《格列佛游记》。在该书中,小人国里爆发了内战,战争起因是人们争论,吃鸡蛋时究竟是从大头(Big-endian)敲开还是从小头(Little-endian)敲开。为了这件事情,前后爆发了六次战争,一个皇帝送了命,另一个皇帝丢了王位。
第一个字节在前,就是"大头方式"(Big endian),第二个字节在前就是"小头方式"(Little endian)。
那么很自然的,就会出现一个问题:计算机怎么知道某一个文件到底采用哪一种方式编码?
Unicode 规范定义,每一个文件的最前面分别加入一个表示编码顺序的字符,这个字符的名字叫做"零宽度非换行空格"(zero width no-break space),用FEFF表示。这正好是两个字节,而且FF比FE大1。
如果一个文本文件的头两个字节是FE FF,就表示该文件采用大头方式;如果头两个字节是FF FE,就表示该文件采用小头方式。
五、java删除字符串中的所有emoji字符
private static final Pattern EMOJI_PATTERN = Pattern.compile("[\\ud83c\\udc00-\\ud83c\\udfff]|[\\ud83d\\udc00-\\ud83d\\udfff]|[\\ud83e\\udc00-\\ud83e\\udfff]|[\\ud83f\\udc00-\\ud83f\\udfff]|[\\u2600-\\u27ff]|[\\u200D]|[\\u0020]|[\\u2642]|[\\u2640]|[\\uFE0F]|[\\u2300-\\u23FF]|[\\udb40\\udc00-\\udb40\\uddff]");/*** 删除字符串中的 emoji 字符* @param source* @param p* @return*/public static CharSequence filterEmoji(CharSequence source, Pattern p) {if (TextUtils.isEmpty(source)) {return "";}return p.matcher(source).replaceAll("");}public static void test(){String test = "哈哈123abc+ \uD83C\uDDFB\uD83C\uDDE6\uD83C\uDDFB\uD83C\uDDE8\uD83C\uDDFB\uD83C\uDDEE\uD83C\uDDFB\uD83C\uDDE6\uD83C\uDDFE\uD83C\uDDEA\uD83C\uDFF4\uDB40\uDC67\uDB40\uDC62\uDB40\uDC77\uDB40\uDC6C\uDB40\uDC73\uDB40\uDC7F\uD83C\uDFF4\uDB40\uDC67\uDB40\uDC62\uDB40\uDC77\uDB40\uDC6C\uDB40\uDC73\uDB40\uDC7F\uD83C\uDDFB\uD83C\uDDEE\uD83C\uDFF4\uDB40\uDC67\uDB40\uDC62\uDB40\uDC77\uDB40\uDC6C\uDB40\uDC73\uDB40\uDC7F\uD83C\uDDFB\uD83C\uDDEE\uD83C\uDDFB\uD83C\uDDE6\uD83C\uDDFB\uD83C\uDDE6\uD83C\uDDFB\uD83C\uDDE6\uD83C\uDDFB\uD83C\uDDEC\uD83C\uDFF4\uDB40\uDC67\uDB40\uDC62\uDB40\uDC77\uDB40\uDC6C\uDB40\uDC73\uDB40\uDC7F\uD83C\uDDFB\uD83C\uDDEE\uD83C\uDFF4\uDB40\uDC67\uDB40\uDC62\uDB40\uDC77\uDB40\uDC6C\uDB40\uDC73\uDB40\uDC7F\uD83C\uDFF4\uDB40\uDC67\uDB40\uDC62\uDB40\uDC77\uDB40\uDC6C\uDB40\uDC73\uDB40\uDC7F\uD83C\uDDFB\uD83C\uDDEE";//这里返回的就是 删除 test 字符串中的所有 eomji字符CharSequence result = filterEmoji(test, EMOJI_PATTERN);}
六、分享两个分析emoji的工具
- unicode编码表查询: https://unicode-table.com/en/#1F600
工具使用截图如下:
- 提取字符串中的所有unicode字符并去重: https://apps.timwhitlock.info/unicode/inspect 。
这个工具有两个用法:其一是将一段肉眼可识别的字符转换成unicode编码;其二是将16进制的unicdoe编码转换成肉眼可识别字符
- 用法截图一:将一段肉眼可识别的字符转换成unicode编码
- 用法截图二:将16进制的unicdoe编码转换成肉眼可识别字符
- 操作步骤:
- 结果展示: 可以看到输入的unicode码 对应的字符
这篇关于android emoji吏上最全的详解的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!