Что такое эквивалент "fread" из Matlab в Python?

я практически не знаю Matlab, и мне нужно перевести некоторые процедуры синтаксического анализа на Python. Они предназначены для больших файлов, которые сами разделены на "блоки", и у меня возникают трудности с контрольной суммой в верхней части файла.

что именно происходит здесь в MATLAB?

status = fseek(fid, 0, 'cof');
fposition = ftell(fid);
disp(' ');
disp(['** Block ',num2str(iBlock),' File Position = ',int2str(fposition)]);

% ----------------- Block Start ------------------ %
[A, count] = fread(fid, 3, 'uint32');
if(count == 3)
    magic_l = A(1);
    magic_h = A(2);
    block_length = A(3);
else
    if(fposition == file_length)
        disp(['** End of file OK']);
    else
        disp(['** Cannot read block start magic !  Note File Length = ',num2str(file_length)]);
    end
    ok = 0;
    break;
end

fid-это файл, который в настоящее время просматривается iBlock-это счетчик, для которого вы находитесь в файле

magic_l и magic_h должны сделать с контрольными суммами позже, Вот код для этого (следует прямо из кода выше):

disp(sprintf('  Magic_L = %08X, Magic_H = %08X, Length = %i', magic_l, magic_h, block_length));
correct_magic_l = hex2dec('4D445254');
correct_magic_h = hex2dec('43494741');

if(magic_l ~= correct_magic_l | magic_h ~= correct_magic_h)
    disp(['** Bad block start magic !']);
    ok = 0;
    return;
end

remaining_length = block_length - 3*4 - 3*4;   % We read Block Header, and we expect a footer
disp(sprintf('  Remaining Block bytes = %i', remaining_length));
  • что происходит с %08X и hex2dec вещи?
  • кроме того, зачем указывать 3*4 вместо 12?

на самом деле, я хочу знать, как реплицировать [A, count] = fread(fid, 3, 'uint32'); в Python, как io.readline() просто тянет первые 3 символа файла. Извини,если я упустил суть. Просто используя io.readline(3) в файле, кажется, возвращается что-то, что он не должен, и я не понимаю, как block_length может поместиться в один байт, когда он потенциально может быть очень длинным.

Спасибо за чтение этой бессвязной. Надеюсь, вы понимаете, что я хочу знать! (Любое понимание вообще приветствуется.)

4 ответов


С документация fread, это функция для чтения двоичных данных. Второй аргумент задает размер выходного вектора, третий-размер/тип считываемых элементов.

чтобы воссоздать это в Python, вы можете использовать array модуль:

f = open(...)
import array
a = array.array("L")  # L is the typecode for uint32
a.fromfile(f, 3)

это будет читать читать три значения uint32 из файла f, которые имеются в a далее. Из документации fromfile:

прочитайте n элементов (как значения машины) из объекта файла f и добавьте их в конец массива. Если доступно менее n элементов, вызывается EOFError, но элементы, которые были доступны, по-прежнему вставляются в массив. f должен быть реальным встроенным файловым объектом; что-то еще с методом read() не будет делать.

массивы реализуют протокол последовательности и поэтому поддерживают те же операции, что и списки, но вы можете также используйте .tolist() метод для создания нормального списка из массива.


код Python для чтения 1-мерного массива

при замене Matlab на Python я хотел прочитать двоичные данные в numpy.array и numpy.fromfile для чтения данных в 1-мерный массив:

import numpy as np

with open(inputfilename, 'rb') as fid:
    data_array = np.fromfile(fid, np.int16)

преимущества использования numpy.fromfile по сравнению с другими решениями Python включают в себя:

  • нет необходимости вручную определять количество элементов для чтения. Вы можете указать их с помощью count= аргумент, но по умолчанию он равен -1 что указывает на чтение всего файла.
  • возможность указать либо открытый объект файла (как я сделал выше с fid) или вы можете указать имя файла. Я предпочитаю использовать объект open file, но если вы хотите использовать имя файла, вы можете заменить две строки выше:

    data_array = numpy.fromfile(inputfilename, numpy.int16)
    

код Matlab для двумерного массива

Матлаб-х fread обладает способностью считывать данные в матрица формы [m, n] вместо того, чтобы просто читать его в вектор-столбец. Например, для считывания данных в матрицу с 2 строк:

fid = fopen(inputfilename, 'r');
data_array = fread(fid, [2, inf], 'int16');
fclose(fid);

эквивалентный код Python для 2-мерного массива

вы можете обрабатывать этот сценарий на языке Python с использованием библиотеки numpy это shape и transpose.

import numpy as np

with open(inputfilename, 'rb') as fid:
    data_array = np.fromfile(fid, np.int16).reshape((-1, 2)).T
  • на -1 говорит numpy.reshape чтобы вывести длину массива для этого измерения на основе другого измерения-эквивалента представление бесконечности.
  • на .T транспонирует массив таким образом, что он представляет собой 2-мерный массив с первым измерением-осью-длиной 2.

На самом деле, я хочу знать, как реплицировать [A, count] = fread(fid, 3, 'uint32');

в Matlab, один из fread()'s подписи fread(fileID, sizeA, precision). Это читается в первом sizeA элементы (не байты) файла, каждый из которых имеет размер, достаточный для precision. В этом случае, так как Вы читаете в uint32, каждый элемент имеет размер 32 бита, или 4 байта.

поэтому вместо этого попробуйте io.readline(12) чтобы получить первые 3 4-байтовых элемента из файла.


первая часть покрыта ответом Торстена... вам понадобится array или numarray делать что-нибудь с этими данными в любом случае.

Что касается %08X и материала hex2dec, %08X - это просто формат печати для этих чисел unit32 (8-значный hex, точно такой же, как Python), а hex2dec ('4D445254') - matlab для 0x4D445254.

наконец, ~ = в matlab-это побитовое сравнение; используйте == в Python.