注意,问题不在于hex到decimal,而在于十六进制值到整数的字符串。假设我从一个hexdump中得到一个字符串(例如,'6c 02 00 00'),所以我需要首先将其转换为实际的hex,然后得到它表示的整数...(这个特定的整数是620,作为int16和int32)我尝试了很多东西,但更多的是让自己感到困惑。在python(最好是3. x)中有没有快速的方法来做这样的转换?
j0pj023g1#
update从Python 3.7开始,bytes.from_hex将忽略空格--所以,最直接的事情就是把字符串解析成一个bytes对象,然后把它看作一个整数:
In [10]: int.from_bytes(bytes.fromhex("6c 02 00 00"), byteorder="little") Out[10]: 620
原答复
它不仅是一个字符串,而且是小端顺序--这意味着只要去掉空格,然后使用int(xx, 16)调用就可以了。它也没有4个任意的0-255数字的实际字节值(在这种情况下struct.unpack就可以工作)。我认为一个很好的方法是将组件交换回“人类可读”的顺序,并使用int调用-因此:
int(xx, 16)
number = int("".join("6c 02 00 00".split()[::-1]), 16)
发生了什么:表达式的第一部分是split--它在空格处将字符串断开,并提供一个包含四个字符串的列表,每个字符串中有两位数。接下来是[::-1]特殊切片--它大致表示“为我提供前一序列中元素的子集,从边缘开始,一次返回一个元素”--这是一个常见的Python习惯用法,用于颠倒任何序列。这个相反的序列被用在"".join(...)的调用中--它基本上使用空字符串作为序列中每个元素的连接符--这个调用的结果是“0000026 c”。使用这个值,我们只调用Python的int类,它接受一个第二可选参数,表示应该用来解释第一个参数中表示的数字的基。
split
"".join(...)
int
>>> int("".join("6c 02 00 00".split()[::-1]), 16) 620
另一个选择是累加每2个数字的转换,根据它们的位置适当地移动到它们的权重-这也可以在使用reduce的单个表达式中完成,尽管4行Python for循环会更可读:
reduce
for
>>> from functools import reduce #not needed in Python2.x >>> reduce(lambda x, y: x + (int(y[1], 16)<<(8 * y[0]) ), enumerate("6c 02 00 00".split()), 0) 620
updateOP只是说他实际上没有字符串中的“空格”--在这种情况下,可以使用abotu相同的方法,但是每两个数字代替split()调用:
split()
reduce(lambda x, y: x + (int(y[1], 16)<<(8 * y[0]//2) ), ((i, a[i:i+2]) for i in range(0, len(a), 2)) , 0)
(当然,其中a是包含您的数字的变量)-或者,将其转换为内存中实际的4字节数字,使用十六进制编解码器,并使用struct解压缩数字-这可能对您的代码来说语义更正确:
a
import codecs import struct struct.unpack("<I", codecs.decode("6c020000", "hex") )[0]
因此,这里的方法是将每2位数字传递给codecs.decode调用返回的bytes对象中内存中的实际字节,并使用struct将缓冲区中的4个字节作为单个32位整数读取。
codecs.decode
cetgtptt2#
可以使用unhexlify()将十六进制字符串转换为二进制形式,然后使用struct.unpack()将little endian值解码为int:
unhexlify()
struct.unpack()
>>> from struct import unpack >>> from binascii import unhexlify >>> n = unpack('<i', unhexlify('6c 02 00 00'.replace(' ','')))[0] >>> n
格式字符串'<i'表示little endian signed integer。您可以用'<I'或'<L'替换unsigned int或long(均为4字节)。如果数据不包含空格,则简化为
'<i'
'<I'
'<L'
>>> n = unpack('<i', unhexlify('6c020000'))[0]
2条答案
按热度按时间j0pj023g1#
update从Python 3.7开始,bytes.from_hex将忽略空格--所以,最直接的事情就是把字符串解析成一个bytes对象,然后把它看作一个整数:
原答复
它不仅是一个字符串,而且是小端顺序--这意味着只要去掉空格,然后使用
int(xx, 16)
调用就可以了。它也没有4个任意的0-255数字的实际字节值(在这种情况下struct.unpack就可以工作)。我认为一个很好的方法是将组件交换回“人类可读”的顺序,并使用int调用-因此:
发生了什么:表达式的第一部分是
split
--它在空格处将字符串断开,并提供一个包含四个字符串的列表,每个字符串中有两位数。接下来是[::-1]特殊切片--它大致表示“为我提供前一序列中元素的子集,从边缘开始,一次返回一个元素”--这是一个常见的Python习惯用法,用于颠倒任何序列。这个相反的序列被用在
"".join(...)
的调用中--它基本上使用空字符串作为序列中每个元素的连接符--这个调用的结果是“0000026 c”。使用这个值,我们只调用Python的int
类,它接受一个第二可选参数,表示应该用来解释第一个参数中表示的数字的基。另一个选择是累加每2个数字的转换,根据它们的位置适当地移动到它们的权重-这也可以在使用
reduce
的单个表达式中完成,尽管4行Pythonfor
循环会更可读:updateOP只是说他实际上没有字符串中的“空格”--在这种情况下,可以使用abotu相同的方法,但是每两个数字代替
split()
调用:(当然,其中
a
是包含您的数字的变量)-或者,将其转换为内存中实际的4字节数字,使用十六进制编解码器,并使用struct解压缩数字-这可能对您的代码来说语义更正确:因此,这里的方法是将每2位数字传递给
codecs.decode
调用返回的bytes对象中内存中的实际字节,并使用struct将缓冲区中的4个字节作为单个32位整数读取。cetgtptt2#
可以使用
unhexlify()
将十六进制字符串转换为二进制形式,然后使用struct.unpack()
将little endian值解码为int:格式字符串
'<i'
表示little endian signed integer。您可以用'<I'
或'<L'
替换unsigned int或long(均为4字节)。如果数据不包含空格,则简化为