Чтение структурированных бинарных файлов
Чтение и запись бинарных файлов
Рассмотрим такой вопрос. Пусть у нас имеется бинарный файл, созданный в программе на языке 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 предоставляет более удобные средства для работы со структурами, однако реализуется за счет сторонней библиотеки.