如何在Python中移动2-5字节长的字节对象中的位?

问题描述 投票:0回答:4

我正在尝试从字节对象中提取数据。例如: 从

b'\x93\x4c\x00'
我的整数隐藏在位 8 到 21 之间。 我尝试做
bytes >> 3
,但是对于超过一个字节来说这是不可能的。 我也尝试用 struct 来解决这个问题,但字节对象必须具有特定的长度。

如何将位向右移动?

python python-3.x binary-data bit-shift
4个回答
10
投票

不要使用

bytes
来表示整数值;如果您需要位,请转换为
int

value = int.from_bytes(your_bytes_value, byteorder='big')
bits_21_to_8 = (value & 0x1fffff) >> 8

其中

0x1fffff
掩码也可以通过以下方式计算:

mask = 2 ** 21 - 1

演示:

>>> your_bytes_value = b'\x93\x4c\x00'
>>> value = int.from_bytes(your_bytes_value, byteorder='big')
>>> (value & 0x1fffff) >> 8
4940

然后您可以使用

int.to_bytes()
方法移回到字节:

>>> ((value & 0x1fffff) >> 8).to_bytes(2, byteorder='big')
b'\x13L'

4
投票

当你有一个字节字符串并且你想去掉最右边的位(即一个字节)时,你可以从字节字符串中简单地删除它:

>>> b'\x93\x4c\x00'[:-1]
b'\x93L'

如果你想将其转换为整数,你可以使用Python的struct来解压它。正如您所说,您需要固定大小才能使用结构,因此您只需填充字节字符串即可添加所需数量的零:

>>> data = b'\x93\x4c\x00'
>>> data[:-1]
b'\x93L'
>>> data[:-1].rjust(4, b'\x00')
b'\x00\x00\x93L'
>>> struct.unpack('>L', data[:-1].rjust(4, b'\x00'))[0]
37708

当然,你也可以先转换,然后将得到的整数移掉8位:

>>> struct.unpack('>Q', data.rjust(8, b'\x00'))[0] >> 8
37708

如果您想确保实际解释的内容不超过这 13 位(第 8 位到 21 位),则必须应用位掩码

0x1FFF
当然:

>>> 37708 & 0x1FFF
4940

(如果您需要大端字节序,只需分别使用

<L
<Q
。)


如果您确实是从左到右计算位(这可能不寻常,但没关系),那么您也可以使用该填充技术:

>>> struct.unpack('>Q', data.ljust(8, b'\x00'))[0] >> 43
1206656

请注意,我们将填充添加到另一侧,并将其移位 43 位(您的 3 位加上 5 个字节用于我们不需要查看的填充数据)


3
投票

适用于任意长字节序列的另一种方法是使用 bitstring 库,它允许对位串进行按位操作,例如

>>> import bitstring
>>> bitstring.BitArray(bytes=b'\x93\x4c\x00') >> 3
BitArray('0x126980')

0
投票

您可以将字节转换为整数,然后乘以或除以二的幂来完成移位

© www.soinside.com 2019 - 2024. All rights reserved.