Unicode字符集收录了全世界所有语言的所有字符,也称万国码。每一个字符都给定一个唯一的Unicode码点值,可以轻松的通过查字典一样的方式得到每个字符的Unicode码点。
但是字符串这种类型数据的传输最终还是需要转换成0和1组成的二进制位,而现在UTF-8这种编码已经成为Unicode字符编码的官方实现标准,即是最常见的Unicode编码方式,另外还有UTF-16等等其他Unicode的编码方式适用于其他的具体场景。
UTF-8编码将Unicode码点转换成的二进制位,按特定形式加工成UTF-8风格的二进制位传输,数据的接收方收到二进制位,顺序读取,根据UTF-8的二进制格式解码成Unicode码点,最终得到字符串的内容。
以中文字符串"世界"为例子来展示UTF-8的编码过程
- 汉字"世"对应的Unicode码点是U+4E16
- 汉字"界"对应的Unicode码点是U+754C
Step1. Unicode码点值转二进制
以汉字"世"为例:
Unicode码点U+4E16由4个十六进制数4E16表示,每个十六进制数[0-9A-F]对应十进制数字的[0-15],转换为二进制数就是4位,范围是[0000~1111]。那么4E这两个十六进制数就占8个二进制位,整个十六进制数4E16一共占16位。(同样的,汉字"界"的码点U+754C转换成二进制也占16位。)
十六进制 4E16 转换成二进制
4 - 0100 # 4 = 2**2
E - 1110 # E(14) = 2**3 + 2**2 + 2**1
1 - 0001 # 1 = 2**0
6 - 0110 # 6 = 2**2 + 2**1
二进制 0100 1110 0001 0110
十六进制 754C 转换成二进制
7 - 0111 # 7 = 2**2 + 2**1 + 2**0
5 - 0101 # 5 = 2**2 + 2**0
4 - 0100 # 4 = 2**2
C - 1100 # C(12) = 2**3 + 2**2
二进制 0111 0101 0100 1100
Step2. 加工成UTF-8编码的二进制
根据UTF-8编码的规则,一个字符可能由1~4的字节表示,具体这个字符是用几个字符表示就要看对应的Unicode码点值了。
Unicode码点值 | 十进制范围 | 字节数表示 |
---|---|---|
U+0000到U+007F | 0-127 | 一个字节(ASCII码) |
U+0080到U+07FF | 128-2047 | 两个字节 |
U+0800到U+0FFFF | 2048-65535 | 三个字节 |
U+10000到U+10FFFF | 65536-1114111 | 四个字节 |
UTF-8编码中,不同字节数表示的二进制形式也有规定,预留高位,其他位则用Unicode码点对应的二进数依次填入,加工成符合UTF-8编码规定的二进制形式。
一个字节 0xxx xxxx
两个字节 110x xxxx 10xx xxxx
三个字节 1110 xxxx 10xx xxxx 10xx xxxx
四个字节 1111 0xxx 10xx xxxx 10xx xxxx 10xx xxxx
汉字"世"的Unicode码点值:U+4E16,十六进制数转成十进制就是19990,在2048~65535这个区间内,所以使用于3个字节的表示。
4E16 转十进制
4 * (16**3)+ 14 * (16**2) + 1 * 16 + 6 = 16384 + 3584 + 16 + 6 = 19990
按三个字节的UTF-8二进制数预留的空位,依次把第一步得到的16位二进制数填进去
1110 xxxx 10xx xxxx 10xx xxxx
1110 0100 1011 1000 1001 0110
得到UTF-8编码格式的二进制数: 1110 0100 1011 1000 1001 0110
汉字"世"的Unicode码点值: U+754C,十六进制数转成十进制就是30028,也在2048~65535这个区间,所以也使用3个字节的表示。
754C 转十进制
7 * (16**3)+ 5 * (16**2) + 4 * 16 + 12 = 28672 + 1280 + 64 + 12 = 30028
按三个字节的UTF-8二进制数预留的空位,依次把第一步得到的16位二进制数填进去
1110 xxxx 10xx xxxx 10xx xxxx
1110 0111 1001 0101 1000 1100
得到UTF-8编码格式的二进制数: 1110 0111 1001 0101 1000 1100
Step3. UTF-8编码的二进制转十六进制
按一个字节,也就是8个二进制位,对二进制的UTF-8编码进行转换:
"世" -> 1110 0100 1011 1000 1001 0110 -> E 4 B 8 9 6
"界" -> 1110 0111 1001 0101 1000 1100 -> E 7 9 5 8 C
Step4. 从汉字到UTF-8编码的十六进制表示的每一阶段
“世”
字符:"世"
-> Unicod码点:U+4E16
-> Unicode码点的二进制表示: 0100 1110 0001 0110
-> UTF-8编码的二进制表示:1110 0100 1011 1000 1001 0110
-> UTF-8编码的十六进制表示:E4 B8 96
“界”
字符:"界"
-> Unicode码点:U+754C
-> Unicode码点的二进制表示: 0111 0101 0100 1100
-> UTF-8编码的二进制表示:1110 0111 1001 0101 1000 1100
-> UTF-8编码的十六进制表示:E7 95 8C