使用python

时间:2015-06-12 13:12:00

标签: python python-3.x hex

请注意,问题不是十六进制到十进制,而是一个十六进制值到整数的字符串。

说我从hexdump中得到了刺痛(例如,' 6c 02 00 00')所以我需要先将其转换为实际的十六进制,然后获取它所代表的整数。 (这个特殊的将是620作为int16和int32)

我尝试了很多东西,但更多地迷惑了自己。有没有快速的方法在python中进行这样的转换(最好是3.x)?

2 个答案:

答案 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]