2015-03-07 3 views
1

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

7A 05 00 00 

Какой должна быть (в соответствии с HEX-> бен конвертер):

0111 1010 0000 0101 0000 0000 0000 0000 

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

Если я использую struct.unpack, я должен использовать Little Endian синтаксический и целое число без знака я думаю, как это:

>>> 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' 

Так что правильный способ разобрать эти биты? В какой-то момент я немного смущен.

UPDATE:

OK Я только что узнал, что спецификатор формата b использует большой 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' 
+0

Ну, мой редактор шестнадцатеричных (Hex Fiend) показывает '7A050000', а также 1402, как беззнаковое целочисленное значение с небольшим обратным порядком байтов. – tamasgal

+1

Модуль ['bitarray'] (https://pypi.python.org/pypi/bitarray/) может быть хорошей альтернативой использованию' struct'. Он позволяет создавать массивы логических значений из последовательности байтов и будет приводить значения нулевого значения (или «False») так, как вы хотите. Он также поддерживает все варианты endian и относительно быстро, так как он написан на C. – martineau

+0

Огромное спасибо! Я проверю это. – tamasgal

ответ

0

чтобы получить целое число значение для строки шестнадцатеричных цифр, попробуйте использовать 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 
Смежные вопросы