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.


¿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.


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.


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]

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


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.


2

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

import codecs

codecs.decode(hexstring, 'hex_codec')

-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

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


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
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.