шестнадцатеричная строка в байтовом массиве в python

150

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

Ричард
источник
Как выглядит эта шестнадцатеричная строка?
Хачик

Ответы:

239

Предположим, что ваша шестнадцатеричная строка похожа на

>>> hex_string = "deadbeef"

Преобразуйте его в строку (Python ≤ 2.7):

>>> hex_data = hex_string.decode("hex")
>>> hex_data
"\xde\xad\xbe\xef"

или начиная с Python 2.7 и Python 3.0:

>>> bytes.fromhex(hex_string)  # Python ≥ 3
b'\xde\xad\xbe\xef'

>>> bytearray.fromhex(hex_string)
bytearray(b'\xde\xad\xbe\xef')

Обратите внимание, что bytesэто неизменяемая версия bytearray.

tzot
источник
27
Если кто-то ищет hex string-> bytesобъект, то это `bytes.fromhex (" 000102030405060708090A0B0C0D0E0F ")`, который дает b'\x00\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x0b\x0c\r\x0e\x0f'. Не публикация в качестве ответа, так как вопрос запрашивает байтовый массив, но публикация здесь, поскольку это первый хит, который я получил при поиске шестнадцатеричных байтов.
матриксаномалия
@Hubro На самом деле, hex_string.decode("hex")работает на Python 2.7. Я только что проверил на своем Python 2.7.10 (default, May 23 2015, 09:44:00) [MSC v.1500 64 bit (AMD64)] on win32.
MewX
@MewX Я сказал Python 3, а не Python 2.7
Hubro
3
Обратите внимание, что bytes.fromhexвыдает ошибку, когда входная строка имеет нечетное количество символов: bytes.fromhex("aab")ValueError: non-hexadecimal number found in fromhex() arg at position 3.
Константин Ван
143

В bytearray есть встроенная функция, которая делает то, что вы собираетесь.

bytearray.fromhex("de ad be ef 00")

Он возвращает байтовый массив и читает шестнадцатеричные строки с разделителем пробелов или без него.

kugg
источник
4
Лучший ответ наверняка!
Майку Мори
5
Это работает в Python 3, тогда как hex_string.decode("hex")нет.
Эрик О Лебиго
15

при условии, что я правильно понял, вы должны искать binascii.unhexlify

import binascii
a='45222e'
s=binascii.unhexlify(a)
b=[ord(x) for x in s]
Брюс
источник
4
Я согласен, что unhexlifyэто самый эффективный способ, но я бы сказал, что b = bytearray(s)это будет лучше, чем использовать ord. Поскольку у Python есть встроенный тип только для массивов байтов, я удивлен, что никто не использует его
Скотт Гриффитс
8

Предполагая, что у вас есть строка байтов, как это

"\ X12 \ x45 \ x00 \ XAB"

и вы знаете количество байтов и их тип, вы также можете использовать этот подход

import struct

bytes = '\x12\x45\x00\xAB'
val = struct.unpack('<BBH', bytes)

#val = (18, 69, 43776)

Как я указал в начале строки формата little endian (используя символ '<'), функция вернула десятичный эквивалент.

0x12 = 18

0x45 = 69

0xAB00 = 43776

B равен одному байту (8 бит) без знака

H равен двум байтам (16 бит) без знака

Более доступные символы и размеры байтов можно найти здесь

Преимущества ..

Вы можете указать более одного байта и порядковый номер значений

Недостатки ..

Вам действительно нужно знать тип и длину данных, с которыми вы имеете дело

Hovo
источник
2
Недостатки: это строка байтов, а не шестнадцатеричная строка, так что это не ответ на вопрос.
Крис
Это ответ на 2-ю часть вопроса «... чтобы я мог сдвинуть каждое значение и преобразовать его в соответствующий тип данных».
Rainald62
2

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

data = "fef0babe"
bits = ""
for x in xrange(0, len(data), 2)
  bits += chr(int(data[x:x+2], 16))

Это, вероятно, не самый быстрый способ (многие строки добавляются), но довольно простой, используя только основной Python.

размотать
источник
-3
def hex2bin(s):
    hex_table = ['0000', '0001', '0010', '0011',
                 '0100', '0101', '0110', '0111',
                 '1000', '1001', '1010', '1011',
                 '1100', '1101', '1110', '1111']
    bits = ''
    for i in range(len(s)):
        bits += hex_table[int(s[i], base=16)]
    return bits
Дмитрий Соболев
источник
-4

Хороший лайнер это:

byte_list = map(ord, hex_string)

Это будет перебирать каждый символ в строке и запускать его через функцию ord (). Только проверено на Python 2.6, не слишком уверен насчет 3.0+.

-Josh

karlw
источник
идеальный. Работа над Python 2.7
Ричард
Нажмите на схему галочки рядом с этим ответом, если он правильный! :)
jathanism
1
Это не конвертирует шестнадцатеричный код - он конвертирует каждый символ строки в целое число. В шестнадцатеричном формате каждая пара символов будет представлять байт. С таким же успехом вы можете просто сказатьbyte_list = bytearray(hex_string)
Скотт Гриффитс