Работа с бинарными данными в Python

Я открываю двоичный файл следующим образом:

file = open("test/test.x", 'rb')

и чтение по строкам в список. Каждая строка выглядит примерно так:

'\xbe\x00\xc8d\xf8d\x08\xe4.\x07~\x03\x9e\x07\xbe\x03\xde\x07\xfe\n'

Мне трудно манипулировать этими данными. Если я попытаюсь напечатать каждую строку, python зависнет и издаст звуковой сигнал (я думаю, что где-то там есть двоичный звуковой код). Как безопасно использовать эти данные? Как преобразовать каждое шестнадцатеричное число в десятичное?


person Dominic Bou-Samra    schedule 17.06.2010    source источник


Ответы (7)


Чтобы распечатать его, вы можете сделать что-то вроде этого:

print repr(data)

Для всего в шестнадцатеричном формате:

print data.encode('hex')

Для десятичного значения каждого байта:

print ' '.join([str(ord(a)) for a in data])

Чтобы распаковать двоичные целые числа и т. д. из данных, как если бы они изначально были получены из структуры в стиле C, см. структура модуля.

person ʇsәɹoɈ    schedule 17.06.2010
comment
Благодарю вас! Это то, что я искал! - person Dominic Bou-Samra; 17.06.2010

\xhh — это символ с шестнадцатеричным значением hh. Другие символы, такие как . и `~', являются обычными символами.

Итерация по строке дает вам символы в ней по одному.

ord(c) вернет целое число, представляющее символ. Например, ord('A') == 65.

Это напечатает десятичные числа для каждого символа:

s = '\xbe\x00\xc8d\xf8d\x08\xe4.\x07~\x03\x9e\x07\xbe\x03\xde\x07\xfe\n'
print ' '.join(str(ord(c)) for c in s)
person Jon-Eric    schedule 17.06.2010
comment
Обратите внимание, что \x07 — это символ ASCII BEL. Вот что вызывает звуковой сигнал. - person dan04; 17.06.2010

Двоичные данные редко делятся на «строки», разделенные символом «\n». Если это так, он будет иметь неявный или явный механизм escape, чтобы различать '\n' как признак конца строки и '\n' как часть данных. Читать такой файл как строки вслепую, не зная механизма выхода, бессмысленно.

Чтобы ответить на ваши конкретные проблемы:

'\x07' - это символ ASCII BEL, который изначально предназначался для звонка в звонок на телетайпе.

Вы можете получить целочисленное значение байта «b», выполнив ord(b).

ОДНАКО, чтобы правильно обрабатывать двоичные данные, вам необходимо знать макет. У вас могут быть целые числа со знаком и без знака (размером 1, 2, 4, 8 байт), числа с плавающей запятой, десятичные числа различной длины, строки фиксированной длины, строки переменной длины и т. д. Дополнительные сложности возникают из-за того, записываются ли данные в бигендианской моде или литэндийской моде. Как только вы узнаете все вышеперечисленное (или сделаете очень обоснованные предположения), модуль структуры Python должен использоваться для всей или большей части вашей обработки; также может быть полезен модуль ctypes.

Есть ли у формата данных имя? Если да, сообщите нам; мы можем указать вам код или документы.

Вы спрашиваете: «Как мне безопасно использовать эти данные?» напрашивается вопрос: для чего вы хотите его использовать? Какие манипуляции вы хотите сделать?

person John Machin    schedule 17.06.2010

Как упоминалось в театре, ord и hex могут вам помочь. Если вы хотите попытаться интерпретировать какие-либо структурированные двоичные данные в файле, struct Модуль может быть полезен.

person Mattias Nilsson    schedule 17.06.2010
comment
+1 за структуру. Правильный способ интерпретировать упакованные двоичные данные. - person Noufal Ibrahim; 17.06.2010

Вы пытаетесь напечатать данные, преобразованные в символы ASCII, что не сработает.

Вы можете смело использовать любой байт данных. Если вы хотите напечатать его как шестнадцатеричный, посмотрите на функции ord и hex/

person Yann Ramin    schedule 17.06.2010

Вы используете read() или readline()? Вы должны использовать read(n) для чтения n байтов; readline() будет читаться до тех пор, пока не встретит новую строку, которой может не быть в двоичном файле.

Однако в любом случае вам возвращается строка байтов, которая может быть печатаемыми или непечатаемыми символами и, вероятно, не очень полезна.

Вам нужно ord(), которое преобразует однобайтовую строку в соответствующее целочисленное значение. read() из файла по одному байту за раз и вызвать ord() для результата или выполнить итерацию по всей строке.

person Paul Richter    schedule 17.06.2010

Если вы хотите использовать NumPy и bitstream, вы можете сделать

>>> from numpy import *
>>> from bitstream import BitStream
>>> raw = '\xbe\x00\xc8d\xf8d\x08\xe4.\x07~\x03\x9e\x07\xbe\x03\xde\x07\xfe\n'
>>> stream = BitStream(raw)
>>> stream.read(raw, uint8, len(stream) // 8)
array([190,   0, 200, 100, 248, 100,   8, 228,  46,   7, 126,   3, 158,
         7, 190,   3, 222,   7, 254,  10], dtype=uint8)
person Sébastien Boisgérault    schedule 13.05.2018