Что является эквивалентом '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
может поместиться в один байт, хотя потенциально он может быть очень длинным.
Спасибо, что прочитали этот бред.Я надеюсь, вы сможете понять примерно то, что я хочу знать!(Любая информация вообще приветствуется.)
Решение
Из самого документация по 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 для чтения одномерного массива
При замене Matlab на Python я хотел считывать двоичные данные в numpy.array
, поэтому я использовал numpy.fromfile
для считывания данных в одномерный массив:
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 для двумерного массива
Matlab's fread
имеет возможность считывать данные в матрицу формы [m, n]
вместо того, чтобы просто считывать его в вектор-столбец.Например, для считывания данных в матрицу из 2 строк используйте:
fid = fopen(inputfilename, 'r');
data_array = fread(fid, [2, inf], 'int16');
fclose(fid);
Эквивалентный код на Python для двумерного массива
Вы можете обработать этот сценарий на 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
чтобы определить длину массива для этого измерения на основе другого измерения —эквивалента Matlab'sinf
представление бесконечности. - Тот Самый
.T
транспонирует массив таким образом, чтобы он представлял собой двумерный массив с первым измерением — осью - длиной 2.
На самом деле, я хочу знать, как воспроизвести
[A, count] = fread(fid, 3, 'uint32');
В Matlab один из fread()
подписи - это fread(fileID, sizeA, precision)
.Это читается в первом sizeA
элементы (не байты) файла, каждый размером, достаточным для precision
.В данном случае, поскольку вы читаете в uint32
, каждый элемент имеет размер 32 бита, или 4 байта.
Так что вместо этого попробуйте io.readline(12)
чтобы получить первые 3 4-байтовых элемента из файла.
Первая часть описана в ответе Торстена...вам понадобится array
или numarray
в любом случае, делать что-либо с этими данными.
Что касается % 08X и содержимого hex2dec, %08X - это просто формат печати для этих чисел unit32 (8-значный шестнадцатеричный код, точно такой же, как в Python), а hex2dec ('4D445254') - это matlab для 0x4D445254.
Наконец, ~= в matlab - это побитовое сравнение;используйте == в Python.