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