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

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

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


1.png


我们知道,在 Unicode 编码中,中文占3个字节,所以一个中文字符编码为 Bytes 型数

据以后,会占用3个 Bytes 字符,例如:


>>> a = '青' 
>>> a.encode() 
b'\xe9\x9d\x92' 
>>> b = '青南' 
>>> b.encode() 
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,如下图所示:


2.png


image.gif如果我把青🤔南转换为 Bytes 型数据,值为:


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


3.png

image.gif

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


4.png

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


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


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


\xe9\x9d\x92 
\xf0\x9f\xa4 
\x94\xe5\x8d\x97


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


11101001 
11100101 
11110000


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


  1. 给定 Bytes 型数据:\xe9\x9d\x92\xf0\x9f\xa4\x94\xe5\x8d\x97


  1. 看第一个字符对应的二进制数的高4位是1110,所以当前字符和它后面两个字符(合计3个字符)一组,进行解析,得到字。



  1. 跳过已经解析的字符,直接来到第四位\xf0,发现它对应的二进制数高4位是1111,所以这个字符和接下来3个字符(合计4个字符)一组,解析出🤔


  1. 跳过已经解析的字符,来到第8位\xe5,对应的二进制高4位是1110,因此这个字符和接下来的两个字符一组进行解析,得到


  1. 完成。对于数字和英文字母,在 Unicode 里面只使用一个字节来表示,他们的 Ascii 码小于128。而多字节的 Unicode 字符,都是从129开头,所以英文字母数字与中文混合生成的 Bytes 型数据,在解码时也不会出现分组不明确的问题。



请关注微信公众号【未闻Code】获取更多精彩文章。

目录
相关文章
|
9月前
2.14 PE结构:地址之间的转换
在可执行文件PE文件结构中,通常我们需要用到地址转换相关知识,PE文件针对地址的规范有三种,其中就包括了`VA`,`RVA`,`FOA`三种,这三种该地址之间的灵活转换也是非常有用的,本节将介绍这些地址范围如何通过编程的方式实现转换。VA(Virtual Address,虚拟地址):它是在进程的虚拟地址空间中的地址,用于在运行时访问内存中的数据和代码。VA是相对于进程基址的偏移量。在不同的进程中,相同的VA可能映射到不同的物理地址。RVA(Relative Virtual Address,相对虚拟地址):它是相对于模块基址(Module Base Address)的偏移量,用于定位模块内部的数
161 1
2.14 PE结构:地址之间的转换
|
18天前
|
安全 C语言 C++
数与字符串相互转化
数与字符串相互转化
10 1
|
1月前
|
存储
一文搞清楚字节的名称和关系,告诉你ib和B有什么区别?
一文搞清楚字节的名称和关系,告诉你ib和B有什么区别?
|
10月前
|
Java
Java——将一组数据固定分组,每组n个元素
Java——将一组数据固定分组,每组n个元素
|
Python
Bytes型数据decode时是如何知道要把几位数据组合在一起的?
Bytes型数据decode时是如何知道要把几位数据组合在一起的?
81 0
有关在不同方式的定义下字符数组求长度
有关在不同方式的定义下字符数组求长度
|
算法 搜索推荐 编译器
一组类型相同的数据【C 数组】总结
一组类型相同的数据【C 数组】总结
|
Oracle 关系型数据库
oracle按code编码长度查询代码展现层级关系(给字段前加空格)
学习oracle按code编码长度查询代码展现层级关系(给字段前加空格)
134 0
oracle按code编码长度查询代码展现层级关系(给字段前加空格)
|
存储
字符串按照固定长度分割并存储在数组
字符串按照固定长度分割并存储在数组
141 0
|
存储 SQL 编解码
base64编码底层转换规则举例解读
base64编码底层转换规则举例解读
221 0
base64编码底层转换规则举例解读