Манипулирование двоичными данными в Python - PullRequest
16 голосов
/ 17 июня 2010

Я открываю бинарный файл примерно так:

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

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

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

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

Ответы [ 7 ]

24 голосов
/ 17 июня 2010

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

print repr(data)

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

print data.encode('hex')

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

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

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

4 голосов
/ 17 июня 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)
2 голосов
/ 17 июня 2010

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

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

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

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

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

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

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

2 голосов
/ 17 июня 2010

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

1 голос
/ 17 июня 2010

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

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

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

1 голос
/ 17 июня 2010

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

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

0 голосов
/ 13 мая 2018

Если вы готовы использовать NumPy и битовый поток , вы можете сделать

>>> 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)
...