Распаковка 4-байтовых целых чисел без знака из двоичного файла дает структуру. ошибка: для распаковки требуется буфер в 4 байта

#python #struct #unpack

#python #struct #распаковать

Вопрос:

Это повторяющийся вопрос, но я не смог найти ответ

Я читаю двоичный файл в следующем формате (просто показываю одну из 3000 строк в шестнадцатеричном формате, как показано в sublime text):

 0009 7f71 0009 b87b 0009 f24b 000a 2ce2
  

Я хочу прочитать его как кортеж из 4-байтовых целых чисел без знака

 if filename:
    with open(filename, mode='rb') as file:
        fileData = file.read()
        unsignedData = struct.unpack('I', fileData )
  

Однако я получаю следующую ошибку для последней строки в приведенном выше коде:

 struct.error: unpack requires a buffer of 4 bytes
  

Как это исправить?

Комментарии:

1. Попробуйте использовать struct.unpack('2I', fileData)

2. @martineau Как мне изменить порядковый номер между большим и маленьким порядковым номером?

3. Смотрите struct документацию модуля.

Ответ №1:

Декодирование нескольких целых чисел

Обычно io.RawIOBase.read возвращается намного больше, чем 4 байта (это ограничено системным вызовом и / или размером файла).

С другой стороны, размер буфера в байтах должен соответствовать размеру, требуемому строкой формата to struct.unpack .

Общая структура данных вашего файла неясна, но, например, для чтения 4 32-разрядных целых чисел без знака, закодированных в строчном порядке (предоставленные вами данные), вы должны разрезать буфер:

 unsignedData = struct.unpack('4I', fileData[:16])
  

Декодирование потока

В случае, если вам нужно декодировать произвольно длинный поток целых чисел из вашего файла, есть несколько вариантов, в зависимости от ожидаемой длины данных.

Короткий поток

 with open(filename, mode='rb') as fp:
    fileData = fp.read()
    n, r = divmod(len(fileData), struct.calcsize('I'))
    assert r == 0, "Data length not a multiple of int size"
    unsignedData = struct.unpack('I' * n, fileData)
  

Длинный поток

Вы могли бы использовать struct.iter_unpack , но, вероятно, имеет смысл хранить большие данные int в array.array or numpy.array в любом случае.

Вот пример для массива NumPy:

 import numpy
data = numpy.fromfile(filename, dtype='uint32')
  

Я оставлю загрузку в однородный массив данных Python в качестве упражнения для читателя (подсказка: array.fromfile ).

Комментарии:

1. Когда я открываю двоичный файл в sublime text, он показывает мне несколько строк в формате «0009 7f71 0009 b87b 0009 f24b 000a 2ce2». Я думаю, что эта строка представляет собой числа в шестнадцатеричном формате. В двоичном файле 3000 таких строк. Я хочу просто интерпретировать байты в файле как 4-байтовый unsigned int и заполнить их внутри кортежа

2. Итак, вы хотите интерпретировать весь файл как (поток) целых чисел?

3. ДА. Поток 4-байтовых целых чисел без знака

4. Хорошо, @nurabha, я расширил свой ответ, включив некоторые параметры декодирования потока.