ciąg szesnastkowy do tablicy bajtów w Pythonie

150

Mam długi ciąg Hex, który reprezentuje serię wartości różnych typów. Chciałbym przekonwertować ten ciąg szesnastkowy na tablicę bajtów, aby móc przesunąć każdą wartość i przekonwertować ją na odpowiedni typ danych.

Richard
źródło
Jak wygląda ten ciąg szesnastkowy?
chaczik

Odpowiedzi:

239

Załóżmy, że twój ciąg szesnastkowy jest podobny

>>> hex_string = "deadbeef"

Zamień go na ciąg (Python ≤ 2,7):

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

lub od wersji Python 2.7 i Python 3.0:

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

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

Zauważ, że bytesjest to niezmienna wersja bytearray.

tzot
źródło
27
Jeśli ktoś szuka szesnastkowego string-> bytesobiektu, to `bytes.fromhex (" 000102030405060708090A0B0C0D0E0F ")` daje wynik b'\x00\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x0b\x0c\r\x0e\x0f'. Nie wysyłanie jako odpowiedź, ponieważ pytanie pyta o tablicę bajtów, ale publikowanie tutaj, ponieważ jest to pierwsze trafienie, które otrzymałem podczas wyszukiwania hext do bajtów.
matrixanomaly
@Hubro Właściwie hex_string.decode("hex")pracuje nad Pythonem 2.7. Właśnie przetestowałem na moim Python 2.7.10 (default, May 23 2015, 09:44:00) [MSC v.1500 64 bit (AMD64)] on win32.
MewX
@MewX Powiedziałem Python 3, a nie Python 2.7
Hubro
3
Zwróć uwagę, że bytes.fromhexzgłasza błąd, gdy ciąg wejściowy ma nieparzystą liczbę znaków: bytes.fromhex("aab")ValueError: non-hexadecimal number found in fromhex() arg at position 3.
Константин Ван
143

W bytearray jest wbudowana funkcja, która robi to, co zamierzasz.

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

Zwraca bajtearray i odczytuje ciągi szesnastkowe z separatorem spacji lub bez niego.

kugg
źródło
4
Najlepsza odpowiedź na pewno!
Maiku Mori
5
Działa to w Pythonie 3, hex_string.decode("hex")ale nie.
Eric O Lebigot
15

pod warunkiem, że dobrze zrozumiałem, powinieneś poszukać binascii.unhexlify

import binascii
a='45222e'
s=binascii.unhexlify(a)
b=[ord(x) for x in s]
Bruce
źródło
4
Zgadzam się, że unhexlifyjest to najskuteczniejszy sposób, aby przejść tutaj, ale sugerowałbym, że b = bytearray(s)byłoby to lepsze niż używanie ord. Ponieważ Python ma wbudowany typ tylko dla tablic bajtów, jestem zaskoczony, że nikt go nie używa
Scott Griffiths
8

Zakładając, że masz taki ciąg bajtów

„\ x12 \ x45 \ x00 \ xAB”

a znasz ilość bajtów i ich typ, możesz również zastosować to podejście

import struct

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

#val = (18, 69, 43776)

Ponieważ określiłem little endian (używając znaku „<”) na początku ciągu formatu, funkcja zwróciła odpowiednik dziesiętny.

0x12 = 18

0x45 = 69

0xAB00 = 43776

B jest równe jednemu bajtowi (8 bitów) bez znaku

H jest równe dwóm bajtom (16 bitów) bez znaku

Więcej dostępnych znaków i rozmiarów bajtów można znaleźć tutaj

Zalety to ...

Możesz określić więcej niż jeden bajt i endian wartości

Niedogodności..

Naprawdę musisz znać rodzaj i długość danych, z którymi masz do czynienia

Hovo
źródło
2
Wady: to jest ciąg bajtów, a nie ciąg szesnastkowy, więc nie jest to odpowiedź na pytanie.
qris
Jest to odpowiedź na drugą część pytania "... abym mógł każdą wartość przesunąć i przekonwertować na jej właściwy typ danych".
Rainald62
2

Powinieneś być w stanie zbudować ciąg przechowujący dane binarne przy użyciu czegoś takiego:

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

Prawdopodobnie nie jest to najszybszy sposób (dołącza wiele ciągów znaków), ale dość prosty przy użyciu tylko podstawowego języka Python.

rozwijać
źródło
2

Możesz użyć modułu Codecs w Python Standard Library, tj

import codecs

codecs.decode(hexstring, 'hex_codec')
velsim
źródło
-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
źródło
-4

Dobra jedna wkładka to:

byte_list = map(ord, hex_string)

Spowoduje to iterację po każdym znaku w ciągu i przeprowadzi go przez funkcję ord (). Testowane tylko na Pythonie 2.6, nie jestem pewien co do wersji 3.0+.

-Josh

karlw
źródło
idealny. Praca nad Pythonem 2.7
Richard
Kliknij zarys znacznika wyboru obok tej odpowiedzi, jeśli jest to właściwa odpowiedź! :)
jathanism
1
To nie konwertuje liczby szesnastkowej - konwertuje każdy znak ciągu na liczbę całkowitą. Dla hex każda para znaków reprezentowałaby bajt. Równie dobrze możesz po prostu powiedziećbyte_list = bytearray(hex_string)
Scott Griffiths