Разбор каждого бита в потоке байтов с помощью 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