Unicode 与 UTF-8 的笔记

前言

之前在项目里遇到过正则查找 ☑ 这个字符,觉得好玩就打印了一下它的 byte 数组

System.out.println(Arrays.toString("☑".getBytes()));

结果是

[-30, -104, -111]

变成二进制以后

[11100010, 10011000, 10010001]

我使用的编码是 UTF-8,说明 ☑ 用了3个字节来表示,然而我发现我已经快忘了 UTF-8 的规则了,赶紧回顾一下

介绍

Unicode 是一个编码方案,Unicode 是为了解决传统的字符编码方案的局限而产生的,它为每种语言中的每个字符设定了统一并且唯一的二进制编码,以满足跨语言、跨平台进行文本转换、处理的要求。Unicode 编码共有三种具体实现,分别为utf-8,utf-16,utf-32,其中utf-8占用一到四个字节,utf-16占用二或四个字节,utf-32占用四个字节。目前Unicode 码在全球范围的信息交换领域均有广泛的应用。

UTF-8 全称 8-bit Unicode Transformation Format,是针对 Unicode 的一种可变长度字符编码,它可以用来表示Unicode标准中的任何字符。

规则

UTF-8 是一种变长的编码方式,它可以使用 1-4 个字节表示一个符号。

Unicode范围 UTF-8编码方式
0000 0000 - 0000 007F 0xxxxxxx
0000 0080 - 0000 07FF 110xxxxx 10xxxxxx
0000 0800 - 0000 FFFF 1110xxxx 10xxxxxx 10xxxxxx
0001 0000 - 0010 FFFF 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx

分析

通过网站查询到 ☑ 的 Unicode 编码是 U+26110010 0110 0001 0001),按照规则的话,在第三个区间,那么编码应该写为

11100010 10011000 10010001

这个结果就和上面打印出来的二进制一样了

同理,再试验一次

的 Unicode 编码是U+54680101 0100 0110 1000),按照规则的话,还是在第三个区间,编码应该写为

11100101 10010001 10101000

试验一下

val bytes = new byte[]{(byte) 0b11100101, (byte) 0b10010001, (byte) 0b10101000};
System.out.println(new String(bytes));

结果

可以 😏