cadena hexadecimal a matriz de bytes en python

150

Tengo una larga cadena hexadecimal que representa una serie de valores de diferentes tipos. Deseo convertir esta cadena hexadecimal en una matriz de bytes para poder cambiar cada valor y convertirlo en su tipo de datos adecuado.

Ricardo
fuente
¿Cómo se ve esa cadena hexadecimal?
khachik

Respuestas:

239

Supongamos que su cadena hexadecimal es algo así como

>>> hex_string = "deadbeef"

Conviértalo a una cadena (Python ≤ 2.7):

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

o desde Python 2.7 y Python 3.0:

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

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

Tenga en cuenta que byteses una versión inmutable de bytearray.

tzot
fuente
27
Si alguien está buscando un hexadecimal string-> bytesobjeto, es `bytes.fromhex (" 000102030405060708090A0B0C0D0E0F ")` que produce b'\x00\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x0b\x0c\r\x0e\x0f'. No publica como respuesta ya que la pregunta solicita una matriz de bytes, pero publica aquí porque es el primer resultado que obtuve al buscar hext a bytes.
matrixanomaly
@Hubro En realidad, hex_string.decode("hex")está trabajando en Python 2.7. Acabo de probar en mi Python 2.7.10 (default, May 23 2015, 09:44:00) [MSC v.1500 64 bit (AMD64)] on win32.
MewX
@MewX Dije Python 3, no Python 2.7
Hubro
3
Tenga en cuenta que bytes.fromhexarroja un error cuando la cadena de entrada tiene un número impar de caracteres: bytes.fromhex("aab")ValueError: non-hexadecimal number found in fromhex() arg at position 3.
Константин Ван
143

Hay una función incorporada en bytearray que hace lo que pretendes.

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

Devuelve un bytearray y lee cadenas hexadecimales con o sin separador de espacio.

kugg
fuente
44
¡La mejor respuesta segura!
Maiku Mori
55
Esto funciona en Python 3, mientras hex_string.decode("hex")que no.
Eric O Lebigot
15

siempre que haya entendido correctamente, debe buscar binascii.unhexlify

import binascii
a='45222e'
s=binascii.unhexlify(a)
b=[ord(x) for x in s]
Bruce
fuente
44
Estoy de acuerdo en que unhexlifyes la forma más eficiente de ir aquí, pero sugeriría que b = bytearray(s)sería mejor que usar ord. Como Python tiene un tipo incorporado sólo para matrices de bytes Me sorprende que nadie lo está utilizando
Scott Griffiths
8

Suponiendo que tiene una cadena de bytes así

"\ x12 \ x45 \ x00 \ xAB"

y sabes la cantidad de bytes y su tipo, también puedes usar este enfoque

import struct

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

#val = (18, 69, 43776)

Como especifiqué little endian (usando el '<' char) al comienzo de la cadena de formato, la función devolvió el equivalente decimal.

0x12 = 18

0x45 = 69

0xAB00 = 43776

B es igual a un byte (8 bits) sin signo

H es igual a dos bytes (16 bits) sin signo

Puede encontrar más caracteres disponibles y tamaños de bytes aquí

Las ventajas son..

Puede especificar más de un byte y el endian de los valores.

Desventajas ..

Realmente necesita saber el tipo y la longitud de los datos con los que trata

Hovo
fuente
2
Desventajas: es una cadena de bytes, no una cadena hexadecimal, por lo que esta no es una respuesta a la pregunta.
qris
Es una respuesta a la segunda parte de la pregunta "... para que pueda cambiar cada valor y convertirlo en su tipo de datos adecuado".
Rainald62
2

Debería poder construir una cadena que contenga los datos binarios usando algo como:

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

Probablemente esta no sea la forma más rápida (se añaden muchas cadenas), pero es bastante simple usando solo Python central.

relajarse
fuente
2

Puede usar el módulo Codecs en la Biblioteca estándar de Python, es decir

import codecs

codecs.decode(hexstring, 'hex_codec')
velsim
fuente
-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
Dmitry Sobolev
fuente
-4

Un buen trazador de líneas es:

byte_list = map(ord, hex_string)

Esto iterará sobre cada carácter en la cadena y lo ejecutará a través de la función ord (). Solo probado en python 2.6, no estoy muy seguro acerca de 3.0+.

-Josh

karlw
fuente
Perfecto. Trabajando en Python 2.7
Richard
¡Haga clic en el contorno de la marca de verificación junto a esta respuesta si es la correcta! :)
jathanism
1
Esto no convierte hexadecimal: convierte cada carácter de una cadena en un entero. Para hexadecimal cada par de caracteres representaría un byte. También podría decirbyte_list = bytearray(hex_string)
Scott Griffiths el