转自:https://www.jianshu.com/p/57c27d67a8a8

背景知识

  • emoji表情符号,是20世纪90年代由NTT Docomo栗田穣崇(Shigetaka Kurit)创建的,词义来自日语(えもじ,e-moji,moji在日语中的含义是字符)。emoji可以使数字通信做到让人如同面对面交流,避免错误传达信息。
  • 在NTT DoCoMo的i-mode系统电话系统中,绘文字的尺寸是12x12 像素,在传送时,一个图形有2个字节。
  • 自苹果公司发布的iOS 5输入法中加入了emoji后,这种表情符号开始席卷全球,目前emoji已被大多数现代计算机系统所兼容的Unicode编码采纳,普遍应用于各种手机短信和社交网络中。
  • 所谓Emoji就是一种在Unicode位于\u1F601-\u1F64F区段的字符。这个显然超过了目前常用的UTF-8字符集的编码范围\u0000-\uFFFF
 
image2015-11-10 19_6_17.png
 
image2015-11-10 19_7_21.png

知识点

  • 在Java里UTF-8,只支持双字节即\u0000-\uFFFF,emoji(马头) => "\uD83D\uDC34"
  • 查Symbola表,我们的目标对象大致是从
    • 1F300-1F3FF => "\uD83C\uDF00" - "\uD83C\uDFFF"
    • 1F400-1F4FF => "\uD83D\uDC00" - "\uD83D\uDCFF"
    • 1F500-1F5FF => "\uD83D\uDD00" - "\uD83D\uDDFF"
    • 1F600-1F6FF => "\uD83D\uDE00" - "\uD83D\uDEFF"
    • 1F700-1F7FF => "\uD83D\uDF00" - "\uD83D\uDFFF"

编码知识

Code UTF-8 UTF-16 LE Surrogates
1F7FF F0 9F 9F BF 3D D8 FF DF D83D DFFF

UTF-16描述

Unicode的编码空间从U+0000到U+10FFFF,共有1,112,064个码位(code point)可用来映射字符. Unicode的编码空间可以划分为17个平面(plane),每个平面包含216(65,536)个码位。17个平面的码位可表示为从U+xx0000到U+xxFFFF,其中xx表示十六进制值从0016到1016,共计17个平面。第一个平面称为基本多语言平面(Basic Multilingual Plane, BMP),或称第零平面(Plane 0)。其他平面称为辅助平面(Supplementary Planes)。基本多语言平面内,从U+D800到U+DFFF之间的码位区段是永久保留不映射到Unicode字符。UTF-16就利用保留下来的0xD800-0xDFFF区段的码位来对辅助平面的字符的码位进行编码。

UTF-16解码

lead \ trail DC00 DC01 DFFF
D800 10000 10001 103FF
D801 10400 10401 107FF
DBFF 10FC00 10FC01 10FFFF

示例:

例如U+10437编码:

  • 0x10437减去0x10000,结果为0x00437,二进制为0000 0000 0100 0011 0111。
  • 分区它的上10位值和下10位值(使用二进制):0000000001 and 0000110111。
  • 添加0xD800到上值,以形成高位:0xD800 + 0x0001 = 0xD801。
  • 添加0xDC00到下值,以形成低位:0xDC00 + 0x0037 = 0xDC37。
  • 下表总结了该转换,以及其它。颜色指示如何从码点位被分布在所述的UTF-16字节。由UTF-16编码过程中加入附加位以黑色显示。
符号 字符 普通二进制 UTF-16二进制 UTF-16 十六进制字符代码 UTF-16BE十六进制字节 UTF-16LE十六进制字节
$ U+0024 0000 0000 0010 0100 0000 0000 0010 0100 0024 00 24 24 00
U+20AC 0010 0000 1010 1100 0010 0000 1010 1100 20AC 20 AC AC 20
  U+10437 0001 0000 0100 0011 0111 1101 1000 0000 0001 1101 1100 0011 0111 D801 DC37 D8 01 DC 37 01 D8 37 DC
  U+24B62 0010 0100 1011 0110 0010 1101 1000 0101 0010 1101 1111 0110 0010 D852 DF62 D8 52 DF 62 52 D8 62 DF

解决方案

一 数据库

  • jar包:mysql connector版本高于5.1.13
  • mysql:utf8mb4的最低mysql版本支持版本为5.5.3+
    • 从utf8改至utf8mb4,需要重启mysql
    • 由于RD不应更改mysql配置,所以需要在业务应用处,调用set names utf8mb4,以使数据以utf8mb4编码存储到数据库

二 过滤

由于数据库的治本方法建立在有数据存储的所有涉猎系统都得满足上述条件,所以并不是常常满足。由此还需要一个治标的方法。

public static void main(String[] args) {
String source = "a\uD83D\uDE36b\uD83D\uDE36\uD83D\uDE36\uD83D\uDE36\uD83C\uDE3612312\uD83C\uDE36";
while (true) {
Integer pos = source.indexOf("\uD83D");
if (pos == -1) {
pos = source.indexOf("\uD83C");
}
if (pos != -1) {
source = source.substring(0, pos) + source.substring(pos + 2);
} else {
break;
}
}
System.out.println(source);
}

参考

https://zh.wikipedia.org/wiki/UTF-16

工具

http://apps.timwhitlock.info/unicode/inspect/hex/1F7FF
emoji符号汇总地址

作者:Lane0x
链接:https://www.jianshu.com/p/57c27d67a8a8
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

特殊字符(包括emoji)梳理和UTF8编码解码原理(转)的更多相关文章

  1. Qt Creator无法用“UTF-8”编码解码

    在Qt Creator 里打开其他编辑器的代码时有时会提示: 无法用"UTF-8"编码解码     在文件上右键使用NotePad++编辑器打开:     选择->格式-&g ...

  2. ajax请求参数中含有特殊字符"#"的问题 (另附上js编码解码的几种方法)

    使用ajax向后台提交的时候 由于参数中含有#  默认会被截断 只保留#之前的字符  json格式的字符串则不会被请求到后台的action 可以使用encodeURIComponent在前台进行编码, ...

  3. VB6的UTF8编码解码

    'UTF-8编码  Public Function UTF8Encode(ByVal szInput As String) As String     Dim wch  As String     D ...

  4. base64编码解码原理

    计算机只能处理数字,所以要处理任何文本,只能先将文本转化为数字才行. Bit(bit)(b) 位或比特,是计算机运行的基础,属于二进制的范畴.数据传输大多是以[位]为单位,一个位即代表一个0或者1(即 ...

  5. 【学习笔记】Base64编码解码原理及手动实现(C#)

    1.[Base64编码原理]@叶落为重生 -base64的编码都是按字符串长度,以每3个8bit的字符为一组,-然后针对每组,首先获取每个字符的ASCII编码,-然后将ASCII编码转换成8bit的二 ...

  6. 通过javascript进行UTF-8编码

    通过javascript进行UTF-8编码 javascript的字符集: javascript程序是使用Unicode字符集编写的.Unicode是ASCII和Latin-1的超集,并支持地球上几乎 ...

  7. HDBn编解码原理 n阶高密度双极性码

    /*------------------------------------------------------------------ HDB3 编码解码原理    // 转载 ---------- ...

  8. JavaScript进行UTF-8编码与解码

    JavaScript本身可通过charCodeAt方法得到一个字符的Unicode编码,并通过fromCharCode方法将Unicode编码转换成对应字符. 但charCodeAt方法得到的应该是一 ...

  9. 【Java】如何检测、替换4个字节的utf-8编码(此范围编码包含emoji表情)

    > 参考的优秀文章 1.十分钟搞清字符集和字符编码 2.Java中byte与16进制字符串的互相转换 3.[异常处理]Incorrect string value: '\xF0\x90\x8D\ ...

随机推荐

  1. JavaScript json loop item in array

    Iterating through/Parsing JSON Object via JavaScript 解答1 Your JSON object is incorrect because it ha ...

  2. 二进制方式安装mysql

    下载官方打包好的rpm的集合 https://downloads.mysql.com/archives/get/file/mysql-5.7.20-1.el7.x86_64.rpm-bundle.ta ...

  3. IDEA 中常用快捷键的使用

    IDEA 中快捷键的使用 1:知道类名全局查找类:   Ctrl+Shift+Alt+N;      全局搜索: Ctrl+Shift+R 2:快速定位到类的文件夹: 3:  优化导入的类和包 (删除 ...

  4. WPF 自定义按钮 Style

    <Style TargetType="{x:Type Button}" x:Key="DefaultButton"> <Setter Prop ...

  5. lambda表达式使用解析

    1.Predicate/Consumer/Function/Supplier介绍 Predicate boolean test(T t); Consumer accpet(T t); Function ...

  6. python 使用 with open() as 读写文件

    读文件: 要以读文件的模式打开一个文件对象,使用Python内置的open()函数,传入文件名和标示符: >>> f = open('E:\python\python\test.tx ...

  7. 应用安全 - 中间件漏洞 - Nostromo

     CVE-2011-0751 Date: 2011.3 类型: 路径遍历 PoC:https://nvd.nist.gov/vuln/detail/CVE-2011-0751 CVE-2019-162 ...

  8. 【DSP开发】【Linux开发】基于ARM+DSP进行应用开发

    针对当前应用的复杂性,SOC芯片更好能能满足应用和媒体的需求,集成众多接口,用ARM做为应用处理器进行多样化的应用开发和用户界面和接口,利用DSP进行算法加速,特别是媒体的编解码算法加速,既能够保持算 ...

  9. 《剑指offer》面试题23 从上往下打印二叉树 Java版

    注意层序遍历的时候对每一层的处理方式可能不同,这里把每一层的元素保存进一个List中了,那么就需要记录每一层的数量. public List<List<Integer>> se ...

  10. Nginx工作机制

    Nginx分为单工作进程和多工作进程两种模式.通常采用1个master+多个worker进程配合异步非阻塞的工作机制.master进程主要负责管理自身和下属的worker进程,worker负责处理请求 ...