Как писал Коди Брошиус, вы можете упаковать весь заголовок сразу:
header = struct.pack('<iiHH', nSamples, nSampPeriod, nSampSize, nParmKind)
Он также упомянул о порядке байтов, что важно, если вы хотите упаковать ваши данные, чтобы надежно распаковать их на компьютерах с различной архитектурой. <
в начале строки моего формата указывает «упаковать эти данные, используя порядок байтов».
Что касается массива, вам нужно будет упаковать его длину, чтобы определить, сколько значений нужно распаковать при повторном чтении. Делаем все за один звонок:
flattened = npVect.ravel() # get a 1-D array of numbers
arrSize = len(flattened)
# pack header, count of numbers, and numbers, all in one call
packed = struct.pack('<iiHHi%df' % arrSize,
nSamples, nSampPeriod, nSampSize, nParmKind, arrSize, *flattened)
В зависимости от размера вашего массива, вы можете получить огромную строку, представляющую все содержимое вашего двоичного файла, и вам может понадобиться поискать альтернативы struct
, которые не требуют от вас иметь весь файл в памяти.
Распаковка:
fmt = '<iiHHi'
nSamples, nSampPeriod, nSampSize, nParmKind, arrSize = struct.unpack(fmt, packed)
# Use unpack_from to start reading after the packed header and count
flattened = struct.unpack_from('<%df' % arrSize, packed, struct.calcsize(fmt))
npVect = np.ndarray(flattened, dtype='float32').reshape(# your dimensions go here
)
РЕДАКТИРОВАТЬ : Ой, формат массива не такой простой, как этот :) Однако общая идея верна: свести массив в список чисел, используя любой метод, который вам нравится, упаковать число значений, затем упакуйте каждое значение. С другой стороны, считайте массив как плоский список, а затем наложите на него любую необходимую вам структуру.
РЕДАКТИРОВАТЬ : Изменены строки формата для использования повторных спецификаторов, а не умножения строк. Спасибо John Machin за указание на это.
EDIT : добавлен код numpy
для выравнивания массива перед упаковкой и восстановления его после распаковки.