如何使用Python从二进制文件解包字节数组?
我正在给自己上一个速成班,学习如何使用Python阅读二进制文件。我对这两个都不熟悉,所以请容忍我 文件格式的文档告诉我,前16个字节是GUID,进一步阅读会告诉我,此GUID的格式如下:如何使用Python从二进制文件解包字节数组?,python,python-3.x,Python,Python 3.x,我正在给自己上一个速成班,学习如何使用Python阅读二进制文件。我对这两个都不熟悉,所以请容忍我 文件格式的文档告诉我,前16个字节是GUID,进一步阅读会告诉我,此GUID的格式如下: typedef struct { unsigned long Data1; unsigned short Data2; unsigned short Data3; byte Data4[8]; } GUID, UUID, *PGUID; 我已经尽可能地让我们能够解包结构中的前三个条目
typedef struct {
unsigned long Data1;
unsigned short Data2;
unsigned short Data3;
byte Data4[8];
} GUID,
UUID,
*PGUID;
我已经尽可能地让我们能够解包结构中的前三个条目,但我在#4上遇到了难题。我想这是一个8字节的数组,但我不知道如何解包
import struct
fp = open("./file.bin", mode='rb')
Data1 = struct.unpack('<L', fp.read(4)) # unsigned long, little-endian
Data2 = struct.unpack('<H', fp.read(2)) # unsigned short, little-endian
Data3 = struct.unpack('<H', fp.read(2)) # unsigned short, little-endian
Data4 = struct.unpack('<s', bytearray(fp.read(8))) # byte array with 8 entries?
struct.error: unpack requires a bytes object of length 1
Python支持的。这样做:
import uuid
my_uuid = uuid.UUID(bytes_le=fp.read(16))
如果您想要一个8字节的字符串,则需要在其中输入数字
8
:
struct.unpack('<8s', bytearray(fp.read(8)))
将字节
转换为字节数组
除了生成可变副本外没有任何效果。解压缩它只会返回一个与开始时相同的字节的副本。那么…为什么
实际上,struct.unpack
返回一个tuple
,它的一个值是您开始使用的相同字节的副本,但是您可以使用:
Data4 = (fp.read(8),)
这就提出了一个问题,为什么首先需要四个单元素元组。你将无缘无故地到处做Data1[0]
,等等。为什么不是这个
Data1, Data2, Data3, Data4 = struct.unpack('<LHH8s', fp.read(16))
但是请记住,Python的uuid使用的是4-2-2-1-1-6格式,而不是4-2-2-8格式。如果您确实需要这种格式,那么您需要转换它,这意味着无论是struct
还是位旋转。(Microsoft的GUID使用了4-2-2-2-6格式,这两种格式都不一样,并且在本机endian中表示前3种格式,在big endian中表示后2种格式,因为它们喜欢使事情变得更简单……如果将struct与bytearray结合使用,这两种格式是不同的。我不熟悉bytearray,但我很确定struct.unpack()
不会接受由bytearray返回的对象,因为它支持。@icktoofay谢谢!很高兴知道!另外,不需要bytearray
(虽然不会有什么伤害)。@icktoofay:你说得对……但是也不需要整个解包
。。谢谢你的评论。非常有帮助,我现在尝试阅读文件的其余部分:)字节
是以大端顺序排列的;OP的数据(假设他得到了struct
格式正确)是以little-endian表示的。因此,这里需要字节,而不是字节
。另外,值得注意的是Python的UUID是4-2-2-1-1-6,而不是4-2-2-8。因此,如果要获得4-2-2-8格式,必须手动转换字段。
Data4 = (fp.read(8),)
Data1, Data2, Data3, Data4 = struct.unpack('<LHH8s', fp.read(16))
data = uuid.UUID(bytes_le=fp.read(16))