Разбор каждого бита в потоке байтов с помощью Python

У меня есть двоичный файл, который содержит наборы байтов для представления различных флагов состояния некоторых модулей. Вот пример 4-байтовой структуры:

7A 05 00 00

Который должен быть (согласно hex->bin конвертеру):

0111 1010 0000 0101 0000 0000 0000 0000

Теперь у меня проблемы с чтением в этих байтах и ​​их разбором по порядку (они в основном представляют значения true/false).

Если я использую 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 использует big endian для преобразования целого числа в представляющую битовую строку:

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

Ведущий ноль (и) по-прежнему отсутствует (есть), поэтому это единственный способ проанализировать биты, чтобы заполнить ведущими нулями, пока я не получу длину 4 байта (32), как это:

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

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
Другие вопросы по тегам