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 个字节表示一个符号。
- 单字节的符号,字节的第一位为0,后面7位为这个符号的 Unicode 码,所以英语字母的 UTF-8 编码和 ASCII 码是一致的。
- 对于
n
字节的符号,第一个字节的前n位都设为1,第n+1位设为0,后面字节的前两位一律设为10,剩下的没有提及的二进制位,全部为这个符号的 Unicode 码。
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+2611
(0010 0110 0001 0001
),按照规则的话,在第三个区间,那么编码应该写为
11100010 10011000 10010001
这个结果就和上面打印出来的二进制一样了
同理,再试验一次
周
的 Unicode 编码是U+5468
(0101 0100 0110 1000
),按照规则的话,还是在第三个区间,编码应该写为
11100101 10010001 10101000
试验一下
val bytes = new byte[]{(byte) 0b11100101, (byte) 0b10010001, (byte) 0b10101000};
System.out.println(new String(bytes));
结果
周
可以 😏