Вопрос

Я практически ничего не знаю о 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's inf представление бесконечности.
  • Тот Самый .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.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top