【问题标题】:Packing data of different sizes into a list of unsigned ints将不同大小的数据打包成一个无符号整数列表
【发布时间】:2012-08-23 20:03:30
【问题描述】:

我有一组数据代表我需要在 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 字节,所以我必须进行两次调用。

因此,对于上面的示例,我需要进行这些调用(为了便于阅读,我将使用大端序):

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,因为它需要一个字符串,而不是数字。

希望我已经把我的问题说清楚了。非常感谢任何帮助!

【问题讨论】:

    标签: python memory pack unpack


    【解决方案1】:

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

    字符串HB 的意思是:打包两个值,一个作为无符号短整型,另一个作为无符号字节。传入两个值就可以了:

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

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

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

    注意开头的“>”,这表示字节序。字符串被转换为序列并作为单独的变量应用。一般来说,只是附加它们更容易:

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

    【讨论】:

    • 我想到了这个,但我认为这里也存在一些问题。例如,这对字节顺序进行了假设。
    • 你可以定义'endianness'
    • @Martin,我不打算提交该回复...我按 Enter 开始新行并错误提交。 :-)
    • @Martin:感谢您的回复。最终,我需要遍历结构的每个字段,因此循环的每次迭代都需要应用不同的格式。你会怎么处理?我只能想到检测数据类型,如果是字符串则附加,如果是数字则打包。你会这样吗?
    • 根本就没有结构吗?例如,您不能存储不同的格式化程序?
    【解决方案2】:

    您可以使用您的结构格式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)
    

    【讨论】:

    • 请注意,OP 要求提供无符号整数。
    猜你喜欢
    • 2020-04-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-10-11
    相关资源
    最近更新 更多