Bezdepbonusu7Программирование: статьи и ответы

Вопрос

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

Автор вопроса: Dominic Bou-SamraОтветов: 7

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

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

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

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

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

pythonbinaryhex

Ответы

Ответ 1 · рейтинг 25 · ʇsәɹoɈ

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

print repr(data)

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

print data.encode('hex')

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

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

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

Ответ 2 · рейтинг 4 · Jon-Eric

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

Ответ 3 · рейтинг 3 · John Machin

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

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

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

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

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

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

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

Ответ 4 · рейтинг 2 · Mattias Nilsson

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

Ответ 5 · рейтинг 1 · Yann Ramin

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

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

Ответ 6 · рейтинг 1 · Paul Richter

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

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

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

Ответ 7 · Sébastien Boisgérault

Если вы хотите использовать 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)

Перевод вопроса и ответов сообщества Stack Overflow, лицензия CC BY-SA. Оригинал на Stack Overflow.

Похожие материалы