Чтение и запись бинарных файлов

Рассмотрим такой вопрос. Пусть у нас имеется бинарный файл, созданный в программе на языке C/C++, содержащий некоторую структуру данных. Нам нужно прочитать эти данные и что-то с ними сделать.

Существует по меньшей мере два способа как это сделать. Рассмотрим их.

пакет structs из набора стандартных библиотек Python

Пусть у нас имеется следующая структура

#pragma pack(push 1)

struct dataBlock{
	int a;
	int b;
	char text[10];
}

#pragma pack(pop)

Наша структура занимает в памяти sizeof(dataBlock)=18 байт. Чтобы прочитать такую структуру мы сперва получим объект bytes.

import struct

fmt="ii10s" #два целочисленных двубайтоых числа и строка из 10
# байтовых символов 
BLOCK_SIZE=struct.calcsize(fmt)
assert BLOCK_SIZE==18

with open("data.bin","rb") as f:
	tmpbuf = f.read(BLOCK_SIZE)
	a, b, text = struct.unpack(fmt, tmpbuf)
	print(f"{a}\t{b}\t{text.decode('utf-8')}")

Таким образом, указывая порядок следования полей в структуре данных можно разбить набор байтов на конкретные числовые значения.

Это все можно обернуть в класс, наделить функциональностью читать и писать себя в файл/буффер и прочее.

Формат следования записей в байтовой строке задается символами форматирования.

Определение нового составного типа при помощи средств NumPy

Чтобы определить структурный тип в NumPy нужно просто описать его следующим образом:

type = [
	(fieldname, datatype, shape)1,
	(fieldname, datatype, shape)2,
	....
	(fieldname, datatype, shape)N
]

Затем создаем сам тип вызывая метод dtype() Пример из кода выше будет таким

import numpy as np
bufType=np.dtype(
	[
		('a', 'i4'),
		('b', 'i4'),
		('text', 'S10')
	]
)

data = np.fromfile('data.bin', dtype=bufType)

print(data)

Обратите внимание, что в последнем случае данные помещаются в массив записей. Доступ к единичной записи осуществляется по индексу, например: data[i]['a'] - получение значения поля a для i-ой структуры массива data. Подробнее о создании массива структур описано в статье “массивы структур”.

Оба эти способа хороши и выбор конкретного зависит от конкретных требований. На мой взгляд, NumPy предоставляет более удобные средства для работы со структурами, однако реализуется за счет сторонней библиотеки.