请注意,问题不是十六进制到十进制,而是一个十六进制值到整数的字符串。
说我从hexdump中得到了刺痛(例如,' 6c 02 00 00')所以我需要先将其转换为实际的十六进制,然后获取它所代表的整数。 (这个特殊的将是620作为int16和int32)
我尝试了很多东西,但更多地迷惑了自己。有没有快速的方法在python中进行这样的转换(最好是3.x)?
答案 0 :(得分:5)
不仅是一个字符串,而且它是以小端顺序 - 只是删除空格,并使用int(xx, 16)
调用将起作用。它也没有实际的字节值作为4个任意0-255数字(在这种情况下struct.unpack可以工作)。
我认为一个很好的方法是将组件交换回“人类可读”的顺序,并使用int调用 - 因此:
number = int("".join("6c 02 00 00".split()[::-1]), 16)
那里发生了什么:第一部分是split
- 它在空格处打破了字符串,并提供了一个包含四个字符串的列表,每个字符串有两个数字。接下来是[:: - 1]特殊切片 - 它大致意味着“从前一个序列中提供元素的子集,从边缘开始,一次返回1个元素” - 这是一个常见的Python习惯用法任何序列。
这个反向序列用于对"".join(...)
的调用 - 它基本上使用空字符串作为序列中每个元素的连接符 - 这个调用的结果是“0000026c”。使用此值,我们只调用Python的int
类,该类接受一个辅助可选参数,表示应该用于解释第一个参数中表示的数字的基数。
>>> int("".join("6c 02 00 00".split()[::-1]), 16)
620
另一种选择,是累计添加每2位数的转换,根据位置适当地移动到它们的权重 - 这也可以使用reduce
在单个表达式中完成,尽管是4行Python {{ 1}}循环将更具可读性:
for
更新 OP刚刚说他在字符串中实际上没有“空格” - 在这种情况下,人们可以使用相同的abotu方法,但是取两个数字而不是{ {1}}致电:
>>> 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
(其中split()
是带数字的变量) -
或者,将其转换为内存中的实际4字节数,使用十六进制编解码器,并使用struct解包数字 - 这可能对您的代码更加语义正确:
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)
所以这里的方法是将每个2位数传递给a
调用返回的字节对象的内存中的实际字节,并将struct作为单个32位整数读取缓冲区中的4个字节。 / p>
答案 1 :(得分:3)
您可以使用unhexlify()
将十六进制字符串转换为二进制形式,然后使用struct.unpack()
将 little endian 值解码为int:
>>> from struct import unpack
>>> from binascii import unhexlify
>>> n = unpack('<i', unhexlify('6c 02 00 00'.replace(' ','')))[0]
>>> n
format string '<i'
表示小端符号整数。您可以使用'<I'
或'<L'
替换unsigned int或long(两个4字节)。
如果数据不包含空格,则简化为
>>> n = unpack('<i', unhexlify('6c020000'))[0]