Модуль struct. Работа с бинарными файлами. Примеры сохранения/чтения упакованных двоичных данных
Содержание
- 1. Применение средств модуля struct для работы с файлами
- 2. Примеры использования средств модуля struct
- Связанные темы
Поиск на других ресурсах:
1. Применение средств модуля struct для работы с файлами
В языке Python модуль struct используется для чтения и сохранения упакованных двоичных данных. Этот модуль содержит ряд методов, которые позволяют получить упакованный объект по указанной строке формата. Более подробно о методах модуля struct можно прочитать здесь.
При работе с бинарными файлами, использование модуля struct может быть применено в следующих случаях:
- во время записи данных в файл, они предварительно упаковываются с помощью методов pack() или pack_into();
- при считывании предварительно записанных упакованных данных, они распаковываются методами unpack() или unpack_into().
⇑
2. Примеры использования средств модуля struct
2.1. Пример записи/чтения разнотипных данных в файл
В примере сначала записываются, а затем читаются данные, которые размещены в списке. Типы данных отличаются: float, bool, char[].
# Бинарные файлы. Запись/чтение списка разнотипных данных. # Использование возможностей модуля struct. # 1. Подключить модуль struct import struct # 2. Заданный список разнотипных данных: # - 1.5 - тип float, в struct обозначен 'f' # - True - тип bool, в struct обозначен '?' # - 'abc def' - тип char[], в struct обозначен 's' L = [1.5, True, 'abc def'] # 3. Запись списка L в файл 'myfile4.bin' # 3.1. Открыть файл для записи f = open('myfile4.bin', 'wb') # 3.2. Записать список в упакованном формате. # Для упаковки данных используется метод pack() # Расшифровка строки '>f?7s': # - '>' - обратный порядок байт (старшие байты следуют последними); # - 'f' - тип float; # - '?' - тип bool; # - '7s' - тип char[] размером 7 символов. d = struct.pack('>f?7s', L[0], L[1], L[2].encode()) # 3.3. Записать упакованные данные d в файл f.write(d) # 3.4. Закрыть файл f.close(); # 4. Прочитать список из бинарного файла 'myfile4.bin' # 4.1. Открыть файл для чтения f = open('myfile4.bin', 'rb') # 4.2. Прочитать данные из файла d = f.read() # 4.3. Распаковать данные с помощью метода unpack(). # Данные распаковываются в виде кортежа. T = struct.unpack('>f?7s', d) # 4.4. Конвертировать кортеж T в список L2 L2 = list(T) # 4.5. Конвертировать строку L2[2] в тип str L2[2] = L2[2].decode() # 4.6. Вывести список print("L2 = ", L2) # L2 = [1.5, True, 'abc def'] # 4.7. Закрыть файл f.close();
Результат работы программы
L2 = [1.5, True, 'abc def']
⇑
2.2. Пример записи/чтения списка, содержащего целые числа
В примере продемонстрирована запись списка в файл и чтение списка из файла. При чтении списка из файла размер записанного ранее списка заведомо неизвестен.
При записи списка происходит поэлементная запись на основе строки формата ‘>i’. В случае чтения, сначала читается количество элементов, а, затем уже читается весь список за один раз с помощью строки
T = struct.unpack('>ni', d)
где
- ‘>ni’ – строка формата, в котором n – количество записанных элементов;
- d – двоичный объект;
- T – кортеж чисел, полученных при распаковывании объекта d.
# Бинарные файлы. Модуль struct. # Пример записи/чтения списка целых чисел # 1. Подключить модуль struct import struct # 2. Заданный список L = [ 2, 4, 6, 8, 10 ] # 3. Запись списка в файл # 3.1. Открыть файл для записи f = open('myfile9.bin', 'wb') # 3.2. Записать список в файл поэлементно # 3.2.1. Получить упакованный объект данных на основе списка s d = struct.pack('>i', len(L)) # 3.2.2. Записать объект d в файл f.write(d) # 3.2.3. Записать элементы по одному - так тоже можно for item in L: d = struct.pack('>i', item) f.write(d) # 3.3. Закрыть файл f.close() # --------------------------------------------- # 4. Чтение списка из файла # 4.1. Открыть файл для чтения f = open('myfile9.bin', 'rb') # 4.2. Считать количество элементов списка - первое число в файле, # считываются первые 4 байта - размер типа int d = f.read(4) # d - двоичный объект count = struct.unpack('>i', d)[0] # 4.3. Считать весь список в двоичный объект d d = f.read() # чтение происходит из текущей позиции до конца файла # 4.4. Сформировать строку формата для чтения всех чисел за один раз # (числа можно также читать по одному в цикле) s = '>' + str(count) + 'i' # 4.5. Получить кортеж из чисел на основе строки формата T = struct.unpack(s, d) # 4.6. Конвертировать кортеж в список L2 = list(T) # 4.7. Вывести список для контроля print("L2 = ", L2) # 4.8. Закрыть файл f.close()
Результат работы программы
L2 = [2, 4, 6, 8, 10]
⇑
2.3. Пример записи/чтения кортежа, содержащего строки
Если в бинарном файле нужно сохранять несколько строк, то при сохранении каждой строки обязательно указывается ее длина, а затем сама строка. Это связано с тем, что строки имеют разную длину.
# Бинарные файлы. Модуль struct. # Пример записи/чтения кортежа строк. # 1. Подключить модуль struct import struct # 2. Заданный кортеж строк, которые нужно записать в файл. T = ( 'abc', 'abcd', 'def', 'ghi jkl') # 3. Запись в файл кортежа T # 3.1. Открыть файл для записи в бинарном режиме f = open('myfile10.bin', 'wb') # 3.2. Записать количество элементов в кортеже count = len(T) d = struct.pack('>i', count) # получить упакованные данные f.write(d) # записать упакованные данные # 3.3. Записать каждую строку кортежа в цикле. # Поскольку каждая строка имеет разную длину, # то эту длину нужно также записывать в файл. for item in T: # цикл обхода элементов кортежа # взять длину строки item length = len(item) # упаковать длину строки length d = struct.pack('>i', length) # записать в файл f.write(d) # упаковать строку item: '>ns' - означает char[n] bt_item = item.encode() # конвертировать str=>bytes d = struct.pack('>' + str(length) + 's', bt_item) # записать в файл f.write(d) # 3.4. Закрыть файл f.close() # ------------------------------------------------------ # 4. Чтение записанного кортежа из файла # 4.1. Открыть файл для чтения в бинарном режиме f = open('myfile10.bin', 'rb') # 4.2. Считать количество элементов (строк) в файле d = f.read(4) # Считать первые 4 байта - размер типа int, d - упакованные данные count = struct.unpack('>i', d)[0] # count - количество элементов # 4.3.Сформировать пустой кортеж-результат T2 = () # 4.4. Цикл чтения строк i = 0 while i<count: # считать длину строки d = f.read(4) length = struct.unpack('>i', d)[0] # length - длина строки # сформировать строку формата sf = '>' + str(length) + 's' # считать length байт из файла в объект d d = f.read(length) # распаковать строку согласно строке sf sb = struct.unpack(sf, d)[0] # sb - строка типа bytes # конвертировать bytes=>str s = sb.decode() # Добавить строку к кортежу T2 = T2 + (s,) i = i+1 # 4.5. Вывести кортеж T2 для контроля print("T2 = ", T2) # 4.6. Закрыть файл f.close()
Результат работы программы
T2 = ('abc', 'abcd', 'def', 'ghi jkl')
⇑
2.4. Пример записи/чтения словаря в котором пара ключ:значение имеет тип int:str
# Бинарные файлы. Модуль struct. # Пример записи/чтения словаря # 1. Подключить модуль struct import struct # 2. Исходный словарь D = { 1:'Sunday', 2:'Monday', 3:'Tuesday', 4:'Wednesday', 5:'Thursday', 6:'Friday', 7:'Saturday' } # 3. Запись в файл кортежа T # 3.1. Открыть файл для записи в бинарном режиме f = open('myfile11.bin', 'wb') # 3.2. Записать количество элементов в словаре count = len(D) d = struct.pack('>i', count) # получить упакованные данные f.write(d) # записать упакованные данные # 3.3. Записать каждую строку словаря в цикле. # Поскольку каждая строка может иметь разную длину, # то эту длину нужно также записывать в файл. for key in D: # цикл обхода элементов словаря # записать ключ - целое число dd = struct.pack('>i', key) f.write(dd) # записать строку по ключу # взять длину строки item length = len(D[key]) # упаковать длину строки length dd = struct.pack('>i', length) # записать в файл длину f.write(dd) # упаковать строку D[key]: '>ns' - означает char[n] bt_item = D[key].encode() # конвертировать str=>bytes dd = struct.pack('>' + str(length) + 's', bt_item) # записать в файл f.write(dd) # 3.4. Закрыть файл f.close() # ------------------------------------------------------ # 4. Чтение записанного кортежа из файла # 4.1. Открыть файл для чтения в двоичном режиме f = open('myfile11.bin', 'rb') # 4.2. Считать количество элементов (строк) в файле dd = f.read(4) # Считать первые 4 байта - размер типа int, d - упакованные данные count = struct.unpack('>i', dd)[0] # count - количество элементов в словаре # 4.3.Сформировать пустой словарь-результат D2 = dict() # 4.4. Цикл чтения строк i = 0 while i<count: # 4.4.1. Считать ключ key - целое число размером 4 байта dkey = f.read(4) key = struct.unpack('>i', dkey)[0] # распаковать данные # 4.4.2. Прочитать количество символов в строке dlength = f.read(4) # 4 - целое число типа int length = struct.unpack('>i', dlength)[0] # 4.4.3. Прочитать строку, предварительно нужно сформировать # строку формата sf sf = '>' + str(length) + 's' ds = f.read(length) # считать из файла length байт sb = struct.unpack(sf, ds)[0] # распаковать строку value = sb.decode() # 4.4.4. Добавить пару key:value к словарю D2 D2[key] = value i = i+1 # 4.5. Вывести словарь D2 для контроля print("D2 = ", D2) # 4.6. Закрыть файл f.close()
Результат работы программы
D2 = {1: 'Sunday', 2: 'Monday', 3: 'Tuesday', 4: 'Wednesday', 5: 'Thursday', 6: 'Friday', 7: 'Saturday'}
⇑
Связанные темы
⇑