Python:从一个字节中提取位

Eva*_*rom 18 python byte bit

我在python中读取二进制文件,文件格式的文档说:

标志(二进制)含义

1 nnn nnnn表示要跟随一个要复制的数据字节nnn nnnn(最多127次).

0 nnn nnnn表示要跟随nnnnnnn字节的图像数据(最多127个字节),并且没有重复.

n 000 0000终点字段.表示行记录的结束.n的值可以是0或1.请注意,行结束字段是必需的,并且它反映在上面提到的行记录字段的长度中.

在读取文件时,我期待我1 nnn nnnn所在的字节返回到nnn nnnn零件应该为50的位置.

我已经能够使用以下方法执行此操作:

flag = byte >> 7
numbytes = int(bin(byte)[3:], 2)
Run Code Online (Sandbox Code Playgroud)

但是,numbytes计算感觉就像一个廉价的解决方法.

我可以做更多的数学运算来完成numbytes的计算吗?

你会怎么做?

Zau*_*bov 14

检查是否设置位的经典方法是使用二进制"和"运算符,即

x = 10 # 1010 in binary
if x & 0b10:  # explicitly: x & 0b0010 != 0
    print('First bit is set')
Run Code Online (Sandbox Code Playgroud)

要检查是否设置了第n位,请使用2的幂或更好的位移位

def is_set(x, n):
    return x & 2 ** n != 0 

    # a more bitwise- and performance-friendly version:
    return x & 1 << n != 0

is_set(10, 1) # 1 i.e. first bit - as the count starts at 0-th bit
>>> True
Run Code Online (Sandbox Code Playgroud)

  • `!= 0` 并不像 `== True` 那样糟糕,但它很接近。:) (2认同)
  • [_Explicit比implicit_更好](http://www.python.org/dev/peps/pep-0020/)所以`x&0b10!= 0`对我没问题 (2认同)

ala*_*lan 10

您可以使用掩码和文件中的字节去掉前导位.这将留下剩余比特的值:

mask =  0b01111111
byte_from_file = 0b10101010
value = mask & byte_from_file
print bin(value)
>> 0b101010
print value
>> 42
Run Code Online (Sandbox Code Playgroud)

在进行位掩码时,我发现二进制数比十六进制更容易理解.

编辑:您的用例稍微更完整的示例:

LEADING_BIT_MASK =  0b10000000
VALUE_MASK = 0b01111111

bytes = [0b10101010, 0b01010101, 0b0000000, 0b10000000]

for byte in bytes:
    value = byte & VALUE_MASK
    has_leading_bit = byte & LEADING_BIT_MASK
    if value == 0:
        print "EOL"
    elif has_leading_bit:
        print "leading one", value
    elif not has_leading_bit:
        print "leading zero", value
Run Code Online (Sandbox Code Playgroud)

  • @EvanBorgstrom在Python 3上,您可以编写:`data = b'\ xaa \ x55 \ x00 \ x80'`和`for data in byte:...`。不要使用“字节”名称,它是内置类型。 (2认同)