Манипулирование двоичными данными в Python
-
28-09-2019 - |
Вопрос
Я открываю двоичный файл следующим образом:
file = open("test/test.x", 'rb')
и чтение по строкам списка.Каждая строка выглядит немного похоже:
'\xbe\x00\xc8d\xf8d\x08\xe4.\x07~\x03\x9e\x07\xbe\x03\xde\x07\xfe\n'
Мне трудно манипулировать этими данными.Если я пытаюсь напечатать каждую строку, python зависает и издает звуковые сигналы (я думаю, что где-то там есть двоичный звуковой код).Как мне безопасно использовать эти данные?Как я могу преобразовать каждое шестнадцатеричное число в десятичное?
Решение
Чтобы распечатать его, вы можете сделать что-то вроде этого:
print repr(data)
В целом, как Hex:
print data.encode('hex')
Для десятичного значения каждого байта:
print ' '.join([str(ord(a)) for a in data])
Распаковать двоичные целыми числами и т. Д. Из данных, как если бы они изначально пришли из структуры стиля C-стиля, посмотрите на распределять модуль.
Другие советы
\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)
Как упомянут театр, орден, и Hex может помочь вам. Если вы хотите попытаться интерпретировать некоторые структурированные двоичные данные в файле, распределять Модуль может быть полезен.
Двоичные данные редко делятся на "строки", разделенные символом " ".Если это так, то у него будет неявный или явный механизм экранирования, позволяющий различать ' ' как ограничитель строки и ' ' как часть данных.Чтение такого файла в виде строк вслепую без знания механизма экранирования бессмысленно.
Чтобы ответить на ваши конкретные вопросы:
"\x07" - это символ ASCII BEL, который первоначально предназначался для вызова звонка на телетайпе.
Вы можете получить целочисленное значение байта "b", выполнив ord(b)
.
ОДНАКО для правильной обработки двоичных данных вам необходимо знать, что это за макет.У вас могут быть целые числа со знаком и без знака (размером 1, 2, 4, 8 байт), числа с плавающей запятой, десятичные числа различной длины, строки фиксированной длины, строки переменной длины и т.д. И т.п.Дополнительная сложность связана с тем, записываются ли данные в формате bigendian или littleendian.Как только вы узнаете все вышесказанное (или у вас появятся очень хорошие обоснованные догадки), Модуль структуры Python должен быть способен использоваться для всей или большей части вашей обработки;тот самый модуль ctypes также может быть полезно.
Есть ли у формата данных название?Если да, сообщите нам;возможно, мы сможем указать вам на код или документы.
Вы спрашиваете: "Как мне безопасно использовать эти данные?" отсюда напрашивается вопрос:Для чего вы хотите это использовать?Какие манипуляции вы хотите произвести?
Вы пытаетесь распечатать данные, преобразованные в символы ASCII, которые не будут работать.
Вы можете безопасно использовать любой байт данных. Если вы хотите распечатать его как шестнадцатеричное, посмотрите на функции ord
а также hex
/
Ты используешь read()
или readline()
? Вы должны использовать read(n)
читать n байтов; readline()
будет читать, пока он не ударит новой строки, которую двоичный файл может не иметь.
В любом случае, хотя вы возвращаете строку байтов, которые могут быть печатными или непечатанными символами, и, вероятно, не очень полезны.
Что вы хотите, это ord()
, который преобразует однобайтовую строку в соответствующее целочисленное значение. read()
из файла один байт за раз и звоните ord()
на результате или итерации через всю строку.
Если вы готовы использовать 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)