UTF‑8 编码原理

UTF‑8是unicode字符集的一种存储实现方式,把每个字符的unicode码点,按规则转换成1~4 个字节

utf8会根据Unicode码点的大小,自动决定用几个字节

先看这张表

utf8编码对应字节数

你的Unicode码点多大

转换为二进制规则

1 字节

很小(0~127)

对应二进制是7位

0xxxxxxx

2 字节

小(128~2047)

对应二进制是8-11位

110xxxxx 10xxxxxx

3 字节

中等(2048~65535)

对应二进制是12-16位

1110xxxx 10xxxxxx 10xxxxxx

4 字节

很大(大于65536)

对应二进制时17位及以上

11110xxx 10xxxxxx 10xxxxxx 10xxxxxx

utf8转码规则:

  1. unicode码点数是二进制7位以内对应1个字节以0开头+原来的7位(正好兼容ASCII码的所有字符)
  2. unicode码点数是二制8~11位对应2个字节:第1个字节110开头+原来的5位,第2个字节10开头加上原来的6位
  3. unicode码点数是二进制12~16位对应3个字节:第1个字节1110开头+原来的4位,第2个和第3个字节10开头加上原来的各6位
  4. unicode码点数是二进制17位以上对应4个字节:第1个字节11110开头+原来的3位,第2个和第3个和第4个字节10开头加上原来的各6位
拿 “中” 字举例

“中” 的Unicode码点=U+4e2d,换算成十进制 =20013,utf8编码为b'\xe4\xb8\xad'

见下面的代码:

s = "中"#ord函数获取十进制码点print(ord(s))#输出为20013# 2. unicode_escape编码:得到转义16进制字符串print(s.encode('unicode_escape'))#输出为b'\中'# 1. utf-8 编码:得到字节(bytes)print(s.encode('utf-8'))# 输出:b'\xe4\xb8\xad'
第1步:根据上面的表数字20013落在哪个范围?
  • 1 字节:0~127 ❌ 不符合
  • 2 字节:128~2047 ❌ 不符合
  • 3 字节:2048~65535 ✅ 正好符合

所以必须用3 字节来存!

U+4e2d是16进制数,换成二进制:0100 1110 0010 1101

s = "中"#bin函数获取对应二进制数print(bin(ord(s)))#输出为 0b100111000101101
第2步:按照3个字节的规则把二进制填进去

原16位:0100 1110 0010 1101

分段:0100 111000 101101

塞进格式:1110xxxx 10xxxxxx 10xxxxxx

重新计算二进制数:11100100 10111000 10101101

第3步:二进制数转成十六进制(我们看到的UTF-8结果)

第2步得到的二进制11100100 10111000 10101101对应16进制数为:e4 b8 ad

所以:“中” 的UTF-8编码 = 0xe4 0xb8 0xad,跟我们上面代码中得到的b'\xe4\xb8\xad'一致。