繁体   English   中英

如何使用Python从二进制文件解压缩字节数组?

[英]How to unpack from a binary file a byte array using Python?

我正在给自己一个使用Python读取二进制文件的速成课程。 我是两个人的新手,所以请耐心等待我。

文件格式的文档告诉我前16个字节是一个GUID,进一步阅读告诉我这个GUID格式化如下:

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

我对Data4做错了什么? (我使用的是Python 3.2 BTW)

Data1到3都可以。 如果我对它们使用hex(),我会得到我期望看到的正确数据(哇哇)我只是对这个字节数组的语法失败了。

编辑:答案

我正在读取MS-DTYP中定义的GUID并将其钉入:

data = uuid.UUID(bytes_le=fp.read(16))

如果你想要一个8字节的字符串,你需要将数字8放在那里:

struct.unpack('<8s', bytearray(fp.read(8)))

来自文档

格式字符之前可以是整数重复计数。 例如,格式字符串'4h'表示与'hhhh'完全相同。

...

对于's'格式字符,计数被解释为字节的长度,而不是像其他格式字符那样的重复计数; 例如,'10s'表示单个10字节字符串,而'10c'表示10个字符。 如果未给出计数,则默认为1.对于打包,字符串将被截断或填充为适当的空字节以使其适合。 对于解包,生成的字节对象始终具有指定的字节数。 作为一种特殊情况,'0'表示单个空字符串(而'0c'表示0个字符)。


但是,我不确定你为什么要这样做。

fp.read(8)为您提供一个8字节的bytes对象。 你想要一个8字节的bytes对象。 所以,就这样做:

Data4 = fp.read(8)

bytes转换为bytearray除了生成可变副本之外没有任何效果。 解压缩它只会返回您开始使用的相同bytes的副本。 所以为什么?


嗯,实际上, struct.unpack返回一个tuple ,其中一个值是您开始使用的相同bytes的副本,但您可以使用以下命令执行此操作:

Data4 = (fp.read(8),)

这就提出了为什么首先需要四个单元素元组的问题。 你将无缘无故地在所有地方做Data1[0]等。 为什么不呢?

Data1, Data2, Data3, Data4 = struct.unpack('<LHH8s', fp.read(16))

当然,如果这是为了阅读UUID,那么使用“包含电池”总是比使用镍和镉矿石制造自己的电池更好。 正如icktoofay所说,只需使用uuid模块:

data = uuid.UUID(bytes_le=fp.read(16))

但请记住,Python的uuid使用4-2-2-1-1-6格式,而不是4-2-2-8格式。 如果你真的需要这种格式,你需要转换它,这意味着无论如何要么struct还是位。 (微软的GUID通过使用4-2-2-2-6格式使事情变得更加有趣,这两种格式都不同,并代表原生端的前3个和大端的最后两个,因为它们喜欢让事情变得简单......)

UUID的是通过用Python支持uuid模块 做这样的事情:

import uuid

my_uuid = uuid.UUID(bytes_le=fp.read(16))

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM