Lesson 5 of 9
Reading structures
- 15 min
- 5 checks
- 3 hints
- Go to task
Goal
Read header fields with the struct module
Explanation
When you open a binary file, you'll usually find a header at the start: a run of fields with fixed sizes, this one two bytes, that one four. Reading them one field at a time with slices and int.from_bytes gets long, which is why Python has the struct module. It reads several fields at once from a short string of format characters:
<or>at the start of the string sets the byte order, little-endian or big-endian.Bis an unsigned byte,His two bytes,Iis four bytes andQis eight.- The lowercase letters
b,h,iandqhave the same sizes but are signed, so they can hold negative values. 4sreads four bytes as they are.
So struct.unpack("<IHB", data) reads four bytes, then two, then one, all little-endian, and returns a tuple with the three values. The length of data must match the total size of the fields exactly, or it raises an error, and struct.calcsize("<IHB") tells you that size. Always put the byte-order character at the start of the string: without it, the module uses your machine's byte order and adds padding between the fields.
Each format string gets a single byte-order character, so if the fields of one header use different orders, you read it in two passes, each with its own string and its own slice of the bytes. The bytes 4d 5a at the start of header are the letters MZ that every Windows executable begins with. Windows itself reads those two bytes as a little-endian number, 0x5A4D, but the made-up header here reads its signature as big-endian so that one lesson covers both orders.
Your task
You have a record header that's seven bytes long. It starts with the magic field in two big-endian bytes, then version in one byte, then length in four little-endian bytes. Write a function parse(data) that reads it with struct.unpack and returns a dictionary with the keys "magic", "version" and "length".
Checks
5 checks- magic is read as big-endian
- version is correct
- length is read as little-endian
- parse works on another header
- The header is read with struct.unpack