特殊字符(包括emoji)梳理和UTF8编码解码原理

2018-04-18  本文已影响1118人  Lane0x

背景知识

image2015-11-10 19_6_17.png
image2015-11-10 19_7_21.png

知识点

编码知识

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编码:

符号 字符 普通二进制 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

解决方案

一 数据库

二 过滤

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

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符号汇总地址

上一篇 下一篇

猜你喜欢

热点阅读