I am trying to unpack a struct from a binary file and I know that the first 4 bytes are an integer (with value 64) and the next 3*8 bytes are three doubles. I have stored the data in a vector called fileContent like this:
with open('data', mode='rb') as file:
fileContent = file.read()
Then I try:
print(struct.unpack("i", fileContent[0:4]))
and this correctly prints the number 64. However, I would like to also read the following double so I modify the statement above to
print(struct.unpack("id", fileContent[0:12]))
(since the integer should be 4 bytes and the double should be 8, yielding a total of 12 bytes). However, I get an error saying that
struct.error: unpack requires a bytes object of length 16
Also, if I try to read the double only and use:
print(struct.unpack("d", fileContent[4:12])
I do not get the correct value of the double! Changing the slicing above to [8:16] gives the correct value. Can someone please explain this? I know for sure that the first 4 bytes in the file should be an integer and the next 8 should be a double. Does read() somehow pad the integer with zeroes, or what is going on?
The unpack()
will automatically do padding for you. So unpack('id', …)
will pad the integer to 8 bytes, that's why you're getting the "struct.error: unpack requires a bytes object of length 16" error.
It can easily be seen like this:
>>> pack('id', 42, 42)
b'*\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00E@'
But the fix is easy, as you know the endianness of the file, you should specify it, and by specifing it, padding will be disabled:
>>> unpadded = pack('>id', 42, 42)
>>> len(unpadded)
12
>>> unpack('>id', unpadded)
(42, 42.0)