Сравнить необработанные байты из файла и не интерпретированные байты str

Итак, у меня есть этот код, который открывает двоичный файл и сравнивает первые «байты» с 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 интерпретировал байты как шестнадцатеричное целое, а не строку?

Заранее спасибо.

Что показывает print(fileStream[0])?

Mark Tolonen 14.12.2020 17:37

вы можете просто преобразовать его как hex(filestream[0])==0x4D

Adi 14.12.2020 17:38

Вы можете проверить это bytes([0x4D])[0] == 0x4D, так что это работает так, как вы ожидаете. Причина, по которой он печатает "no", вероятно, в том, что первый байт не 0x4D.

a_guest 14.12.2020 17:40

@AdityaChavan Вы хотите использовать ord вместо hex? hex не делает того, что кажется вам нужным.

Brian61354270 14.12.2020 17:41

См. редактирование @a_guest

Alex 14.12.2020 17:42
0xE42F — целочисленный литерал, выраженный в шестнадцатеричном формате. fileStream[0:2] является экземпляром класса bytes — это то, чего вы не понимаете.
martineau 14.12.2020 17:46

@martineau да, однако fileStream[0:2] возвращает странную шестнадцатеричную строку, и я хочу преобразовать все в одну шестнадцатеричную строку

Alex 14.12.2020 17:46

Пожалуйста, правильно формулируйте свои предложения: «где 0x2F интерпретируется как /» не имеет смысла.

Aaj Kaal 14.12.2020 17:51

Python (как ни странно) будет отображать представление '\xE4\x2F' как 'ä/', а bytes([0xE4, 0x2F]) как b'\xe4/'. Другими словами, если будут отображаться значения, которые являются порядковым значением символов в качестве символа, а не шестнадцатеричным значением.

martineau 14.12.2020 17:53

@martineau ах да, есть ли способ отобразить шестнадцатеричные значения?

Alex 14.12.2020 17:55

Пожалуйста, смотрите мой ответ ниже, где первые два байта читаются и печатаются. Если это служит вашей цели, то зачем конвертировать в шестнадцатеричный. Очень важно также указать конечную цель.

Aaj Kaal 14.12.2020 17:58

@AajKaal Я четко указал, какова моя конечная цель в моем обновленном посте, мой вопрос состоял не в том, чтобы узнать, каковы первые два байта исполняемого файла (взятые в качестве примера), а в том, как я могу по-разному интерпретировать произвольные байты для моего сравнения, в этом случае байты не были напечатаны полностью, так как 0x2F был напечатан как /.

Alex 14.12.2020 18:00

Алекс: Да. Один из способов — создать собственный подкласс и определить его метод __repr__(), чтобы он делал то, что вы хотите. Другим было бы просто написать свою собственную служебную функцию, которая сделала бы это.

martineau 14.12.2020 18:09
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
0
13
2 024
5
Перейти к ответу Данный вопрос помечен как решенный

Ответы 5

Использовать 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'

Мой вопрос не об этом, пожалуйста, перечитайте мой пост.

Alex 14.12.2020 17:44

Пожалуйста, перечитайте мой ответ. Это на 100% служит вашей цели, упомянутой в вопросе.

Aaj Kaal 14.12.2020 18:02

Попробуй это:

если формат(fileStream[0:2],'x') == '4d':

это возвращается unsupported format string passed to bytes.__format__

Alex 14.12.2020 17:48

Я забыл - сначала я использую struct.unpack(), но я вижу, что кто-то уже опубликовал это.

Aldo 14.12.2020 18:00
Ответ принят как подходящий

Использование среза объекта bytes дает вам другой объект bytes, поэтому вам нужно сравнивать с объектом bytes (а не с объектом str).

>>> bytes([0x4D, 0x5A])
b'MZ'
>>> bytes([0x4D, 0x5A]) == b'MZ'
True

Я не знал о существовании байтовых объектов на питоне, что прояснило ситуацию. Спасибо

Alex 14.12.2020 17:53

@Alex Да, именно префикс b определяет разницу между объектом str и bytes.

a_guest 14.12.2020 17:54

о, хорошо, это имеет смысл, спасибо.

Alex 14.12.2020 17:55

Кажется, вы хотите переинтерпретировать первые два байта файла как 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 всегда возвращает кортеж, даже для одного элемента, поэтому вам нужно индексировать его.

Другие вопросы по теме