【问题标题】:Reading Bits from a byte with python用python从一个字节中读取位
【发布时间】:2020-11-04 16:10:54
【问题描述】:

我有关于二进制文件结构的说明,我正在尝试构建解析器以从二进制文件中获取信息。在遇到以下情况之前,我做得很好:

从 DWORD 大小 = 0 开始。您将通过以下方式重建大小 获取 7 位数据包:

  1. 获取一个字节。

  2. 将此字节的前 7 位添加到 Size。

  3. 检查此字节的第 7 位(最后一位)。如果开启,则返回 1. 处理下一个字节。

要恢复,如果 Size

我感到困惑的是“从字节中获取位”和“检查字节的最后一位”的含义。 这是我从文件中读取字节的方式:


    from struct import *
    #..... some other blocks of code
    self.standard = {"DWORD":4,"WORD": 2,"BYTE": 1,"TEXT11": 1,"TEXT12": 2}
    st = st = self.standard
    size = 0
    data = unpack("b", f.read(st["BYTE"]))
    #how to get bits???
    if size < 128:
        #use st["TEXT11"]
    elif size < 16384:
        #use st["TEXT12"]

【问题讨论】:

  • 它实际上并没有“从一个字节中获取位”。作者所说的“最后一位”显然是指价值的最高位。
  • @Kinrad Rudolph 一开始我也是这么认为的,但我认为它们在第 3 步中参考 0 编号,例如 0、1、2、3、4、5、6、7。所以 7 基本上是第 8 位
  • @KonradRudolph 在讨论数据格式时,值的位通常从 0 向上编号,因此字节大小的值的最高有效位是位 7,而不是(不存在的)位 8。

标签: python file binary byte


【解决方案1】:

我很困惑的是“从一个字节中获取位”是什么意思

您使用位操作来做到这一点。例如,要获取字节的前(低)7 位,请使用

byte & 127

或者,等价地,

byte & 0x7f

或者

byte & 0b1111111

在您的情况下,byte 将是元组 data 的第一个也是唯一一个成员。

要获得 last 位,您需要屏蔽该位(使用&amp;)并将其位移到位(使用&gt;&gt;) - 尽管在您的情况下,因为您只需要检查是否设置好了,移位不是绝对必要的。

【讨论】:

  • 嘿,谢谢你的回复。但是在什么情况下我实际上必须进行位移>>
  • @TochiBedford 例如,您可以在一个字节中存储两个彼此相邻的四位数字。要阅读第一个数字,您可以使用b &amp; 0b1111。要读取第二个数字,您可以执行b &amp; 0b11110000,但现在该数字被移动了四位,您需要将其向下移动以获得它的值。例如,以前如何存储神奇宝贝精灵图像的宽度和高度。
  • 在玩过这些例子之后。我有这个想法,是否可以通过这种方式检查最后一位是否已设置? bin(data[0])[-1] == "0" 。还是不好的做法?
  • @TochiBedford 是的,这是非常糟糕的做法。首先,它的代码更多,更难阅读。尤其是一旦你熟悉了位操作,它就会比位操作的简单逻辑复杂得多,因为它必须执行更多的工作。最后,它的效率也低得多。对于单个操作,您不会注意到差异,但如果您在循环中多次执行此操作,您可能会注意到它的效率降低了大约 100 倍(!)(可能不是在 Python 中,但可能在 C 中)。
【解决方案2】:

也许混淆与整数的二进制表示有关,例如,如果我们有数字171,它就相当于这个二进制配置(1字节):

val = 0b10101011 # (bit configuration)
print(val) # -> 171 (integer value)

现在您可以使用位掩码只允许传递其中的 1 个位 (big endian notation):

print(val & 0b00000001) # -> only the first bit pass and then it prints 1
print(val & 0b10000000) # -> only the latest bit pass and then it prints 128
print(val & 0b00000100) # -> it prints 0 because val does not have a 1 to the third position

然后,要检查第七位是否为 1,您可以执行以下操作:

print((val & 0b01000000) >> 6)
# val    = 0b10101011
#             ^
# mask   = 0b01000000
# result = 0b00000000 -> 0 (integer)
# shift  =    ^123456 -> 0b0

位移位(&gt;&gt; 运算符)允许您获得位掩码的结果。

例如,如果你想要第二个位:

print((val & 0b00000010) >> 1)
# val    = 0b10101011
#                  ^
# mask   = 0b00000010
# result = 0b00000010 -> 2 (integer)
# shift  =         ^1 -> 1b0 -> 1 (integer)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-04-14
    • 2013-02-21
    • 1970-01-01
    • 1970-01-01
    • 2016-09-24
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多