【问题标题】:Parse each bit in a byte stream with Python使用 Python 解析字节流中的每一位
【发布时间】:2015-05-09 04:16:34
【问题描述】:

我有一个二进制文件,其中包含表示某些模块的不同状态标志的字节集。下面是一个 4 字节结构的例子:

7A 05 00 00

应该是(根据 hex->bin 转换器):

0111 1010 0000 0101 0000 0000 0000 0000

现在我无法读取这些字节并按顺序解析它们(它们基本上代表真/假值)。

如果我使用struct.unpack,我猜我必须使用小端解析和无符号整数,如下所示:

>>> with open('the_file.dat', 'rb') as f:
...     b = f.read(4)
>>> struct.unpack('I', b)[0]
1402

如果我将 1402 转换回整数,我会得到完全不同的位,当然不是 32 位,因为前导零被切断了:

>>> "{0:b}".format(1402)
'10101111010'

那么解析这些位的正确方法是什么?在这一点上我有点困惑。

更新:

好的,我刚刚发现格式说明符b 使用大端序将整数转换为表示位串:

>>> struct.unpack('<I', b)[0]
1402
>>> struct.unpack('>I', b)[0]
2047148032
>>> "{0:b}".format(2047148032)
'1111010000001010000000000000000'

前导零仍然丢失,因此解析位以填充前导零的唯一方法是,直到我有 4 个字节 (32) 的长度,如下所示:

>>> "{0:032b}".format(2047148032)
'01111010000001010000000000000000'

【问题讨论】:

  • 好吧,我的十六进制编辑器 (Hex Fiend) 显示 7A050000 和 1402 为 unsigned int 和 little endian。
  • bitarray 模块可能是使用 struct 的一个很好的替代方案。它允许您从字节序列创建布尔值数组,并以您想要的方式提供前导零(或False)值。它还支持所有的字节序变体,并且相对较快,因为它是用 C 编写的。
  • 非常感谢!我去看看。

标签: python struct bit-manipulation byte unpack


【解决方案1】:

要获得一串十六进制数字的整数值,请尝试使用 int 进行转换。如果八位字节由空格分隔,您可以使用replace 将其删除:

intvalue = int('7A 05 00 00'.replace(' ', ''), base=16)

如果你想要一个表示二进制值的字符串,你可以使用bin() 来生成一个二进制字符串:

bin(int('7A 05 00 00'.replace(' ', ''), base=16))

产量:'0b1111010000001010000000000000000'.

如果您想从前面删除'0b',您可以将字符串的前两个字符切掉:

bin(int('7A 05 00 00'.replace(' ', ''), base=16))[2:]

请注意,如果要检查特定标志,则应不要使用字符串形式,而应使用整数形式的位运算符来检查特定位。要检查是否设置了位 i,您可以使用:

intval & (1 << i) != 0

【讨论】:

    猜你喜欢
    • 2015-09-09
    • 1970-01-01
    • 2019-07-15
    • 1970-01-01
    • 2019-09-18
    • 2023-02-25
    • 1970-01-01
    • 1970-01-01
    • 2021-08-11
    相关资源
    最近更新 更多