2016-02-24 2 views
0

У меня есть строка ANSI Ď–ór˙rXüď\ő‡íQl7, и мне нужно преобразовать ее в шестнадцатеричный: 06cf96f30a7258fcef5cf587ed51156c37 (преобразованный с XVI32).Как преобразовать строку байта с непечатаемыми символами в шестнадцатеричный в python?

Проблема заключается в том, что Python не может правильно кодировать все символы (некоторые из них отображаются неправильно даже здесь, при переполнении стека), поэтому мне приходится иметь дело с ними с байтовой строкой.

Так выше строка в байтах этого: b'\x06\xcf\x96\xf3\nr\x83\xffrX\xfc\xef\\\xf5\x87\xedQ\x15l7'

И это то, что мне нужно преобразовать в шестнадцатеричное.

До сих пор я пытался binascii без успеха, я попытался это:

h = "" 
for i in b'\x06\xcf\x96\xf3\nr\x83\xffrX\xfc\xef\\\xf5\x87\xedQ\x15l7': 
    h += hex(i) 
print(h) 

Он печатает:

0x60xcf0x960xf30xa0x720x830xff0x720x580xfc0xef0x5c0xf50x870xed0x510x150x6c0x37

Хорошо. Похоже, я куда-то ... но что случилось с 0x?

Когда я удалить 0x из строки, как это:

h.replace("0x", "") 

я 6cf96f3a7283ff7258fcef5cf587ed51156c37, который выглядит, как это правильно.

Но иногда строка байтов имеет 0 рядом с x и удаляется из строки, что приводит к неправильной шестнадцатеричной строке. (в приведенной выше строке отсутствует 0 в начале).

Любые идеи?

ответ

3

Если вы работаете питон 3.5+, bytes типа имеет новый метод bytes.hex(), который возвращает строковое представление.

>>> h = b'\x06\xcf\x96\xf3\nr\x83\xffrX\xfc\xef\\\xf5\x87\xedQ\x15l7' 
b'\x06\xcf\x96\xf3\nr\x83\xffrX\xfc\xef\\\xf5\x87\xedQ\x15l7' 
>>> h.hex() 
'06cf96f30a7283ff7258fcef5cf587ed51156c37' 

В противном случае вы можете использовать binascii.hexlify(), чтобы сделать то же самое

>>> import binascii 
>>> binascii.hexlify(h).decode('utf8') 
'06cf96f30a7283ff7258fcef5cf587ed51156c37' 
+0

Ничего себе, я не знаю, что. Это здорово, спасибо! – poke

+0

и в обратном порядке: 'h = bytes.fromhex ('06cf96f30a7283ff7258fcef5cf587ed51156c37')'. – jfs

+1

На Python 2 вы можете использовать 'h.encode ('hex')'. – jfs

0

Согласно документации, hex() преобразует «целое число в нижнем регистре шестнадцатеричной строки с префиксом„0x“.» Таким образом, при использовании hex() вы всегда получите 0x префикс. Вам всегда придется удалить это, если вы хотите объединить несколько шестнадцатеричных представлений.

Но иногда строка байт имеет 0 рядом с x и он получает удаляется из строки, что приводит к неправильному шестнадцатеричной строки. (в начале строки отсутствует 0).

Это не имеет никакого смысла. x не является допустимым шестнадцатеричным символом, поэтому в вашем решении может быть только будет вызван вызовом hex(). И это, как сказано выше, всегда будет создавать 0x. Таким образом, последовательность 0x может никогда не выглядит иначе в вашей результирующей строке, поэтому замена 0x ничем не должна работать нормально.

актуальная проблема в вашем решении является то, что hex() не обеспечивает результат двузначный, просто как показано на этом примере:

>>> hex(10) 
'0xa' 
>>> hex(2) 
'0x2' 

Так что в вашем случае, поскольку строка начинается с b\x06, который представляет собой номер 6, hex(6) возвращает 0x6, поэтому вы можете получить только одну цифру, которая является реальной причиной вашей проблемы.

Что вы можете сделать, это использовать строки формата для преобразования в шестнадцатеричный. Таким образом, вы можете обойти префикс и обеспечить длину двух цифр. Затем вы можете использовать str.join, чтобы объединить все это в одной шестнадцатеричной строки:

>>> value = b'\x06\xcf\x96\xf3\nr\x83\xffrX\xfc\xef\\\xf5\x87\xedQ\x15l7' 
>>> ''.join(['{:02x}'.format(x) for x in value]) 
'06cf96f30a7283ff7258fcef5cf587ed51156c37' 

Это решение не только работать со строкой байтов, но с действительно все, что может быть отформатирован как шестнадцатеричную строку (например, целое число, список) :

>>> value = [1, 2, 3, 4] 
>>> ''.join(['{:02x}'.format(x) for x in value]) 
'01020304' 
Смежные вопросы