三个一组还是四个一组?从 Bytes 到 Unicode 的字节划分方法

开发 后端
大家在 Python 开发过程中,经常会进行字符串encode为 Bytes型数据,或者把 Bytes 型数据 decode为字符串的操作。

[[421316]]

大家在 Python 开发过程中,经常会进行字符串encode为 Bytes型数据,或者把 Bytes 型数据 decode为字符串的操作。例如:图片我们知道,在 Unicode 编码中,中文占3个字节,所以一个中文字符编码为 Bytes 型数据以后,会占用3个 Bytes 字符,例如:

  1. >>> a = '青'  
  2. >>> a.encode()  
  3. b'\xe9\x9d\x92'  
  4. >>> b = '青南'  
  5. >>> b.encode()  
  6. b'\xe9\x9d\x92\xe5\x8d\x97'  

注意这里的\xe9需要作为整体来看待,表示一个16进制数。

所以,当我要把 Bytes 型数据\xe9\x9d\x92\xe5\x8d\x97 转为字符串时,Python 会把\xe9\x9d\x92转成青字,把\xe5\x8d\x97转成南字,看起来,似乎是 Python 知道应该把每3个 Bytes 符号一组来进行处理。

然而,Unicode 中,emoji 表情是4个字节,例如表情符号:

??,它对应的 Bytes 型数据为:

\xf0\x9f\xa4\x94,如下图所示:

如果我把青??南转换为 Bytes 型数据,值为:

\xe9\x9d\x92\xf0\x9f\xa4\x94\xe5\x8d\x97,如下图所示,一共10个 Bytes 字符:

那么问题来了,当我对这个 Bytes 型数据进行 decode 会怎么样呢?如下图所示:

Python 可以正确地把 Bytes 数据划分为:

  1. \xe9\x9d\x92 对应“青”  
  2. \xf0\x9f\xa4\x94 对应“🤔”  
  3. \xe5\x8d\x97 对应“南”  

为什么 Python 知道要把\xf0\x9f\xa4\x94这4个符号分到一组?为什么不会像下面这样分组?

  1. \xe9\x9d\x92  
  2. \xf0\x9f\xa4  
  3. \x94\xe5\x8d\x97  

实际上,这个问题的原因,只有当我们用二进制来看的时候,才能发现端倪。 青对应的第一个 Bytes 字符\xe9,其中的e9是一个十六进制数字,把它转成十进制是233,转成二进制是11101001。 南对应的第一个 Bytes 字符\xe5,其中的e5是一个十六进制数字,把它转成十进制是229,转成二进制是11100101。 ??对应的第一个 Bytes 字符\xf0,其中的f0是一个十六进制数字,把它转成十进制是240,转成二进制是11110000。如果还看不出他们的差异,那我们把他们放在一起对比一下:

  1. 11101001  
  2. 11100101  
  3. 11110000  

看出差异了吗?中文汉字是三个字节,转换为 Bytes 型数据以后,第一个字符对应的二进制数是1110开头。emoji 是4个字节,转换为 Bytes 型数据以后,第一个字符对应的二进制数是1111开头。所以,当给定一个 Bytes 型数据需要给 Python 来转换为字符串的时候,Python 是这样判断应该有几个字符一组的。

 

  • 给定 Bytes 型数据:\xe9\x9d\x92\xf0\x9f\xa4\x94\xe5\x8d\x97
  • 看第一个字符对应的二进制数的高4位是1110,所以当前字符和它后面两个字符(合计3个字符)一组,进行解析,得到青字。
  • 跳过已经解析的字符,直接来到第四位\xf0,发现它对应的二进制数高4位是1111,所以这个字符和接下来3个字符(合计4个字符)一组,解析出??。
  • 跳过已经解析的字符,来到第8位\xe5,对应的二进制高4位是1110,因此这个字符和接下来的两个字符一组进行解析,得到南。
  • 完成。对于数字和英文字母,在 Unicode 里面只使用一个字节来表示,他们的 Ascii 码小于128。而多字节的 Unicode 字符,都是从129开头,所以英文字母数字与中文混合生成的 Bytes 型数据,在解码时也不会出现分组不明确的问题。

本文转载自微信公众号「未闻Code」,可以通过以下二维码关注。转载本文请联系未闻Code公众号。

 

责任编辑:武晓燕 来源: 未闻Code
相关推荐

2019-11-01 11:19:25

转链表LeetCode代码

2016-11-28 10:06:57

戴尔峰会

2012-03-06 10:13:14

诺基亚应用商店运营商

2015-04-07 09:44:49

Android

2012-05-14 10:01:12

PaaS云计算平台即服务

2019-10-28 11:18:23

戴尔

2019-09-03 08:57:52

Linux命令软件

2023-04-07 07:30:30

数据库调研数据

2019-07-26 07:02:05

TCP四次挥手网络协议

2023-09-15 07:33:25

数据库选型评估

2018-08-22 09:40:27

2012-12-26 10:34:56

CSSWeb前端

2009-07-10 09:58:09

Chrome OS屏幕造假谷歌

2023-04-19 08:00:00

人工智能视觉语言模型

2019-04-23 14:52:26

2018-05-07 15:23:51

2019-11-11 10:20:10

Linux重命名命令

2015-02-28 10:01:10

工信部FDD LTE4G

2009-09-15 09:13:29

Linux服务器僵尸网络恶意软件

2021-05-24 11:05:53

代码开发Go
点赞
收藏

51CTO技术栈公众号