簡體   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