Итак, у меня есть этот код, который открывает двоичный файл и сравнивает первые «байты» с 0xE42F:
file = open("hello.bin", "rb")
fileStream = file.read()
if (fileStream[0:2] == '\xE4\x2F'):
print("yes")
else:
print("no")
Однако приведенная выше проверка возвращает false, поскольку для python выбранные байты интерпретируются как строка hex => \xE4/
, где 0x2F
интерпретируется как строка (/
), и, следовательно, проверка возвращает false.
Когда я пытаюсь использовать hex(fileStream[0:2])
, он возвращает invalid literal for int
Любая идея о том, как я мог бы сделать так, чтобы python интерпретировал байты как шестнадцатеричное целое, а не строку?
Заранее спасибо.
вы можете просто преобразовать его как hex(filestream[0])==0x4D
Вы можете проверить это bytes([0x4D])[0] == 0x4D
, так что это работает так, как вы ожидаете. Причина, по которой он печатает "no"
, вероятно, в том, что первый байт не 0x4D
.
@AdityaChavan Вы хотите использовать ord
вместо hex
? hex
не делает того, что кажется вам нужным.
См. редактирование @a_guest
0xE42F
— целочисленный литерал, выраженный в шестнадцатеричном формате. fileStream[0:2]
является экземпляром класса bytes
— это то, чего вы не понимаете.
@martineau да, однако fileStream[0:2] возвращает странную шестнадцатеричную строку, и я хочу преобразовать все в одну шестнадцатеричную строку
Пожалуйста, правильно формулируйте свои предложения: «где 0x2F интерпретируется как /» не имеет смысла.
Python (как ни странно) будет отображать представление '\xE4\x2F'
как 'ä/'
, а bytes([0xE4, 0x2F])
как b'\xe4/'
. Другими словами, если будут отображаться значения, которые являются порядковым значением символов в качестве символа, а не шестнадцатеричным значением.
@martineau ах да, есть ли способ отобразить шестнадцатеричные значения?
Пожалуйста, смотрите мой ответ ниже, где первые два байта читаются и печатаются. Если это служит вашей цели, то зачем конвертировать в шестнадцатеричный. Очень важно также указать конечную цель.
@AajKaal Я четко указал, какова моя конечная цель в моем обновленном посте, мой вопрос состоял не в том, чтобы узнать, каковы первые два байта исполняемого файла (взятые в качестве примера), а в том, как я могу по-разному интерпретировать произвольные байты для моего сравнения, в этом случае байты не были напечатаны полностью, так как 0x2F был напечатан как /
.
Алекс: Да. Один из способов — создать собственный подкласс и определить его метод __repr__()
, чтобы он делал то, что вы хотите. Другим было бы просто написать свою собственную служебную функцию, которая сделала бы это.
Использовать fileStream = байты (file.read()) Это работало с .exe
После вашего редактирования:
fileStream = bytes(file.read())
if fileStream[0] == 0xE4 and fileStream[1] == 0x2F:
...
Что бы ни показал python, это правильно. Первые два байта EXE-файла всегда 4D 5A, которые представляют собой коды ASCII двух букв MZ.
Код:
file = open(r"python.exe", "rb")
fileStream = file.read()
print(fileStream[0:2])
file.close()
Выход:
b'MZ'
Мой вопрос не об этом, пожалуйста, перечитайте мой пост.
Пожалуйста, перечитайте мой ответ. Это на 100% служит вашей цели, упомянутой в вопросе.
Попробуй это:
если формат(fileStream[0:2],'x') == '4d':
это возвращается unsupported format string passed to bytes.__format__
Я забыл - сначала я использую struct.unpack(), но я вижу, что кто-то уже опубликовал это.
Использование среза объекта bytes
дает вам другой объект bytes
, поэтому вам нужно сравнивать с объектом bytes (а не с объектом str
).
>>> bytes([0x4D, 0x5A])
b'MZ'
>>> bytes([0x4D, 0x5A]) == b'MZ'
True
Я не знал о существовании байтовых объектов на питоне, что прояснило ситуацию. Спасибо
@Alex Да, именно префикс b
определяет разницу между объектом str
и bytes
.
о, хорошо, это имеет смысл, спасибо.
Кажется, вы хотите переинтерпретировать первые два байта файла как short unsigned int
, чтобы получить значение 0xe42f.
Чтобы сделать это в Python, вам нужно использовать структурный модуль.
Теперь я собираюсь предположить, что байты в вашем файле находятся в порядке с обратным порядком байтов, то есть первый байт равен 0xe4, второй байт равен 0x2f.
Если они перепутаны, просто переключите первый символ первого параметра на unpack
в коде с '>' на '<'.
import struct
file = open("hello.bin", "rb")
fileStream = file.read()
if (struct.unpack(">H", fileStream[0:2])[0] == 0xE42F):
print("yes")
else:
print("no")
Обратите внимание, что struct.unpack
всегда возвращает кортеж, даже для одного элемента, поэтому вам нужно индексировать его.
Что показывает
print(fileStream[0])
?