将不同大小的数据打包成无符号整数列表

时间:2012-08-23 20:03:31

标签: python memory pack unpack

我有一组数据代表我需要在python中操作的硬件结构。真正的结构大小为4 KB ......我只是简单地举例说明:

Byte(s)  Value  
0-1      0x0102
2-3      0x0304
4-23     "AStrWith20Characters"
24-63    "WoahThisStringHas40CharactersItIsHuge!!!"
64-71    "Only8Chr"
72-74    0x050607
74       0x08
75-127   0x00 (padding)

我的想法是将这个结构打包成32位Int列表,将列表传递给另一个函数,然后 函数将整个shebang写入内存。内存写入功能一次接受64字节,因此我必须进行两次调用。

因此,对于上面的示例,我需要进行这些调用(我将使用big endian来实现可读性):

WrToMemory([0x01020304, 0x41537472, 0x57697468, 0x3230436, 
            0x61726163, 0x74657273, 0x576F6168, 0x5468697, 
            0x53747269, 0x6E674861, 0x73343043, 0x6861726, 
            0x63746572, 0x73497449, 0x73487567, 0x65212121])

WrToMemory([0x4F6E6C79, 0x38436872, 0x05060708, 0x00000000,  
            0x00000000, 0x00000000, 0x00000000, 0x00000000,  
            0x00000000, 0x00000000, 0x00000000, 0x00000000,  
            0x00000000, 0x00000000, 0x00000000, 0x00000000])    

问题在于我不知道如何以任何有效的方式打包这些数据。我一直在努力使用structarray,但要么我在概念上遗漏了某些东西,要么就是在使用错误的工具。

最终,我知道我可以写一个大毛茸茸的函数来检查数据类型,做一堆移位和屏蔽,将ASCII转换为十六进制,以及构造我需要的数据包。但这似乎......不优雅。

我认为必须有一种方法来告诉python“这是一个两个字节长的数字。打包它。另外两个字节数,将它附加到最后一个。现在这是一个字符串,有20个字节添加它。继续直到我们有64个字节。然后将我们刚制作的64个字节的列表转换为16个无符号整数的lsit。

似乎packunpack函数是我应该使用的函数,但就像我上面所说的那样......我必须遗漏一些东西。例如,pack如何处理3字节数?如果您使用类似HB的格式字符串,则pack需要两个参数:

>>> pack('HB', 0x050607)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
struct.error: pack requires exactly 2 arguments

我不能使用unpack,因为它需要一个字符串,而不是一个数字。

希望我的问题清楚。非常感谢任何帮助!

2 个答案:

答案 0 :(得分:2)

您正在使用正确的工具,但您告诉pack编码2个参数,但只传入一个。

字符串HB表示:打包两个值,一个作为无符号短整数,另一个作为无符号字节。传递两个值,它可以工作:

>>> pack('HB', 0x0506, 0x07)
'\x06\x05\x07'

只要继续尝试,你就会掌握它。以下是您的示例中的第一组值,采用Big Endian表示法:

>>> pack('>2H20c40c', 0x0102, 0x0304)
'\x01\x02\x03\x04AStrWith20CharactersWoahThisStringHas40CharactersItIsHuge!!!'

请注意'&gt;'一开始,这标志着结束。字符串将转换为序列并作为单个变量应用。一般来说,通过追加它们会更容易:

>>> pack('>2H20c40c', 0x0102, 0x0304) + "AStrWith20Characters" + "WoahThisStringHas40CharactersItIsHuge!!!"
'\x01\x02\x03\x04AStrWith20CharactersWoahThisStringHas40CharactersItIsHuge!!!'

答案 1 :(得分:0)

你可以使用你的结构格式pack整个事情,并使用例如32位字格式:

>>> format="cchi"
>>> p=pack(format,"a","b",1,2)
>>> p
'ab\x01\x00\x02\x00\x00\x00'
>>> (z1,z2)=unpack("ii",p)
>>> (z1,z2)
(90721, 2)