Evan Borgstrom Evan Borgstrom - 1 year ago 108
Python Question

Python: Extracting bits from a byte

I'm reading a binary file in python and the documentation for the file format says:

Flag (in binary)Meaning

1 nnn nnnn Indicates that there is one data byte to follow
that is to be duplicated nnn nnnn (127 maximum)

0 nnn nnnn Indicates that there are nnn nnnn bytes of image
data to follow (127 bytes maximum) and that
there are no duplications.

n 000 0000 End of line field. Indicates the end of a line
record. The value of n may be either zero or one.
Note that the end of line field is required and
that it is reflected in the length of line record
field mentioned above.

When reading the file I'm expecting the byte I'm at to return
1 nnn nnnn
where the
nnn nnnn
part should be 50.

I've been able to do this using the following:

flag = byte >> 7
numbytes = int(bin(byte)[3:], 2)

But the numbytes calculation feels like a cheap workaround.

Can I do more bit math to accomplish the calculation of numbytes?

How would you approach this?

Answer Source

You can strip off the leading bit using a mask ANDed with a byte from file. That will leave you with the value of the remaining bits:

mask =  0b01111111
byte_from_file = 0b10101010
value = mask & byte_from_file
print bin(value)
>> 0b101010
print value
>> 42

I find the binary numbers easier to understand than hex when doing bit-masking.

EDIT: Slightly more complete example for your use case:

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
Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download