Python. Module struct. Working with binary files




Module struct. Working with binary files. Examples of writing/reading packed binary data


Contents


Search other websites:

1.Using tools of struct module for working with files

In Python, the struct module is used to read and save packed binary data. This module contains a number of methods that allow you to get a packed object on a specified format string. You can read more about the methods of the struct module here.

Before using the struct module, you need to connect it with the directive

import struct

When working with binary files, the use of the struct module can be applied in the following cases:

  • while writing data to a file, they are pre-packaged using the pack() or pack_into() methods;
  • when reading pre-recorded packed data, they are unpacked using the unpack() or unpack_into() methods.

 

2. Examples of using the tools of the struct module
2.1. Example of writing/reading different types of data to a file

In the example, the data that is placed in the list is first written and then read. Data types are different: float, bool, char[].

# Binary files. Writing/reading a list of different data.
# Using the capabilities of the struct module.

# 1. Include the struct module
import struct

# 2. The specified list of different types of data:
#   - 1.5 - type float, in struct denoted by 'f'
#   - True - type bool, in struct denoted by '?'
#   - 'abc def' - type char[], in struct denoted 's'
L = [1.5, True, 'abc def']

# 3. Write list L to the file 'myfile4.bin'
# 3.1. Open file for writing
f = open('myfile4.bin', 'wb')

# 3.2. Write the list in packed format.
#     To pack data, use the pack() method
#     Decoding the string '>f?7s':
#     - '>' - reverse byte order (high bytes follow last);
#     - 'f' - type float;
#     - '?' - type bool;
#     - '7s' - the type char[] of 7 character size.
d = struct.pack('>f?7s', L[0], L[1], L[2].encode())

# 3.3. Write pack data d in file
f.write(d)

# 3.4. Close file
f.close();

# 4. Read the list from the binary file 'myfile4.bin'
# 4.1. Open file for reading
f = open('myfile4.bin', 'rb')

# 4.2. Read data from file
d = f.read()

# 4.3. Unpack data using the unpack() method.
#      Data is unpacked as a tuple.
T = struct.unpack('>f?7s', d)

# 4.4. Convert tuple T to list L2
L2 = list(T)

# 4.5. Convert string L2[2] to str type
L2[2] = L2[2].decode()

# 4.6. Print the list
print("L2 = ", L2) # L2 =   [1.5, True, 'abc def']

# 4.7. Close the file
f.close();

The result of the program

L2 = [1.5, True, 'abc def']

 



2.2. Example of writing/reading a list containing integers

The example demonstrates writing a list to a file and reading a list from a file. When reading a list from a file, the size of the previously written list is not known.

When writing a list, item-by-item writing is performed based on a ‘>i’ format string. In the case of reading, the number of elements is read first, and then the entire list is already read at a time using the line

T = struct.unpack('>ni', d)

where

  • ‘>ni’ – format string in which n is the number of written elements;
  • d – binary object;
  • T – a tuple of numbers obtained by unpacking the object d.

 

# Binary files. Module struct.
# Example of writing/reading a list of integers

# 1. Include the struct module
import struct

# 2. Specified list
L = [ 2, 4, 6, 8, 10 ]

# 3. Write list to the file
# 3.1. Open file for writing
f = open('myfile9.bin', 'wb')

# 3.2. Write a list to a file element by element
# 3.2.1. Get packed data object based on list s
d = struct.pack('>i', len(L))

# 3.2.2. Write object d to the file
f.write(d)

# 3.2.3. Write elements one at a time - this is also possible
for item in L:
    d = struct.pack('>i', item)
    f.write(d)

# 3.3. Close file
f.close()

# ---------------------------------------------
# 4. Reading a list from a file
# 4.1. Open file for reading
f = open('myfile9.bin', 'rb')

# 4.2. Get the number of list items - the first number in the file,
#     first 4 bytes are read - int type size
d = f.read(4) # d - binary object
count = struct.unpack('>i', d)[0]

# 4.3. Read the entire list into a binary object d
d = f.read() # reading occurs from the current position to the end of the file

# 4.4. Generate a format string to read all numbers at a time
#      (numbers can also be read one at a time in a loop)
s = '>' + str(count) + 'i'

# 4.5. Get a tuple of numbers based on a format string
T = struct.unpack(s, d)

# 4.6. Convert tuple to a list
L2 = list(T)

# 4.7. Print the list
print("L2 = ", L2)

# 4.8. Close file
f.close()

The result of the program

L2 = [2, 4, 6, 8, 10]

 

2.3. Example of writing/reading a tuple containing strings

If you need to save several lines in a binary file, then when saving each line, its length must be indicated, and then the line itself. This is because strings have different lengths.

# Binary files. Module struct.
# Example of writing/reading a tuple of strings.

# 1. Connect the struct module
import struct

# 2. The specified tuple of rows to be written to the file.
T = ( 'abc', 'abcd', 'def', 'ghi jkl')

# 3. Writing to a file tuple T
# 3.1. Open file for writing in binary mode
f = open('myfile10.bin', 'wb')

# 3.2. Write the number of elements in a tuple
count = len(T)
d = struct.pack('>i', count) # get the packed data
f.write(d) # write the packed data

# 3.3. Write each row of the tuple in a loop.
#     Since each line has a different length,
#     this length must also be written to the file.
for item in T: # the loop bypassing of elements of the tuple
    # get the length of item
    length = len(item)

    # pack the length of item
    d = struct.pack('>i', length)

    # write to the file
    f.write(d)

    # pack the string item: '>ns' - means char [n]
    bt_item = item.encode() # convert str=>bytes
    d = struct.pack('>' + str(length) + 's', bt_item)

    # write to the file
    f.write(d)

# 3.4. Close file
f.close()

# ------------------------------------------------------
# 4. Reading a recorded tuple from a file
# 4.1. Open file for reading in binary mode
f = open('myfile10.bin', 'rb')

# 4.2. Count the number of elements (lines) in a file
d = f.read(4) # Read the first 4 bytes - size of type int, d - packed data
count = struct.unpack('>i', d)[0] # count - number of elements

# 4.3.Generate an empty tuple
T2 = ()

# 4.4. Lines reading cycle
i = 0
while i<count:
    # get the length of the line
    d = f.read(4)
    length = struct.unpack('>i', d)[0]

    # create a format string
    sf = '>' + str(length) + 's'

    # read length bytes from file to object d
    d = f.read(length)

    # unpack the string according to the sf line
    sb = struct.unpack(sf, d)[0] # sb - string of type bytes

    # convert bytes=>str
    s = sb.decode()

    # Add string to the tuple
    T2 = T2 + (s,)

    i = i+1

# 4.5. Print the tuple T2
print("T2 = ", T2)

# 4.6. Close file
f.close()

The result of the program

T2 = ('abc', 'abcd', 'def', 'ghi jkl')

 

2.4. An example of writing/reading a dictionary in which a key:value pair is of type int:str

 

# Binary files. Module struct.
# Example of writing/reading dictionary

# 1. Include the struct module
import struct

# 2. Specified dictionary
D = { 1:'Sunday', 2:'Monday', 3:'Tuesday', 4:'Wednesday',
      5:'Thursday', 6:'Friday', 7:'Saturday' }

# 3. Write tuple T to the file
# 3.1. Open file for writing in binary mode
f = open('myfile11.bin', 'wb')

# 3.2. Write the number of items in the dictionary
count = len(D)
d = struct.pack('>i', count) # get packed data
f.write(d) # write packed data

# 3.3. Write each line of the dictionary in a loop.
#     Since each line can have a different length,
#     this length must also be written to a file.
for key in D: # dictionary traversal cycle
    # write key - int number
    dd = struct.pack('>i', key)
    f.write(dd)

    # write line by key
    # get the length of line item
    length = len(D[key])

    # pack the length of the string
    dd = struct.pack('>i', length)

    # write length to the file
    f.write(dd)

    # pack string D[key]: '>ns' - means char[n]
    bt_item = D[key].encode() # convert str=>bytes
    dd = struct.pack('>' + str(length) + 's', bt_item)

    # write to file
    f.write(dd)

# 3.4. Close file
f.close()

# ------------------------------------------------------
# 4. Reading a recorded tuple from a file
# 4.1. Open file for reading in binary mode
f = open('myfile11.bin', 'rb')

# 4.2. Count the number of elements (lines) in a file
dd = f.read(4) # Read the first 4 bytes - size of type int, d - packed data
count = struct.unpack('>i', dd)[0] # count - number of items in the dictionary

# 4.3.Form an empty dictionary
D2 = dict()

# 4.4. Lines reading loop
i = 0
while i<count:
    # 4.4.1. Read key - an integer of 4 bytes
    dkey = f.read(4)
    key = struct.unpack('>i', dkey)[0] # unpack data

    # 4.4.2. Read the number of characters per line
    dlength = f.read(4) # 4 - the number of type int
    length = struct.unpack('>i', dlength)[0]

    # 4.4.3. Read the line, first you need to form
    #        the sf format line
    sf = '>' + str(length) + 's'
    ds = f.read(length) # read length bytes from file
    sb = struct.unpack(sf, ds)[0] # unpack string
    value = sb.decode()

    # 4.4.4. Add pair key:value to the dictionary D2
    D2[key] = value

    i = i+1

# 4.5. Display the dictionary D2
print("D2 = ", D2)

# 4.6. Close file
f.close()

The result of the program

D2 = {1: 'Sunday', 2: 'Monday', 3: 'Tuesday', 4: 'Wednesday', 5: 'Thursday', 6: 'Friday', 7: 'Saturday'}

 


Related topics