Создайте новые системные объекты для входа и выхода файлов

В этом примере показано, как создать и использовать два различных системных объектов для облегчения потоковой передачи данных в и из MATLAB ®: TextFileReader и TextFileWriter.

Объекты, обсуждаемые в этом примере, касаются ряда реалистичных вариантов использования, и они могут быть настроены для достижения более продвинутых и специализированных задач.

Введение

Системные объекты являются классами MATLAB, которые получают из matlab.System. В результате все системные объекты наследуют общий открытый интерфейс, который включает стандартные методы:

  • setup - Инициализируйте объект, обычно в начале симуляции

  • reset - Очистить внутреннее состояние объекта, вернув его к статусу постинициализации по умолчанию

  • release - Отпустите любые ресурсы (память, оборудование или ресурсы ОС), используемые внутри объекта

Когда вы создаете новые виды системных объектов, вы обеспечиваете определенные реализации для всех предыдущих методов, чтобы определить его поведение.

В этом примере мы обсуждаем внутреннюю структуру и использование следующих двух системных объектов:

  • TextFileReader

  • TextFileWriter

Чтобы создать эти Системные объекты для потоковой передачи данных в MATLAB и из него, этот пример использует стандартные низкоуровневые функции ввода-вывода файлов, доступные в MATLAB (например fscanf, fread, fprintf, и fwrite). Абстрагируя большинство деталей использования этих функций, они стремятся сделать задачу чтения и записи потоковых данных более простой и эффективной.

Этот пример включает использование ряда расширенных конструкций для создания системных объектов. Для получения дополнительной информации об авторских системных объектах см. раздел «Создание системных объектов».

Определение TextFileReader классов

The TextFileReader класс включает определение класса, общие и частную собственность, конструктор, защищенные методы, переопределенные из matlab.System базовый класс и частные методы. The TextFileWriter класс аналогично структурирован.

Определение класса

Определение класса утверждает, что TextFileReader класс получают из обоих matlab.System и matlab.system.mixin.FiniteSource.

   classdef (StrictDefaults)TextFileReader < matlab.System & matlab.system.mixin.FiniteSource
  • matlab.System является обязательным и базовым классом для всех системных объектов

  • matlab.system.mixin.FiniteSource указывает, что этот класс является источником сигнала с конечным количеством выборок данных. Для этого типа класса, в дополнение к обычному интерфейсу, системный объект также предоставляет isDone функция. Когда isDone возвращает true, объект достиг конца доступных данных.

Общественная собственность

Общественная собственность могут быть изменены пользователем, чтобы настроить поведение объекта к его конкретному приложению. TextFileReader имеет два неотключаемых общедоступных свойства (их можно изменить только перед первым вызовом объекта) и четыре настраиваемых общедоступных свойства. Все общественная собственность имеют значение по умолчанию. Значения по умолчанию присваиваются соответствующим свойствам, если пользователь не задает ничего другого.

   properties (Nontunable)
       Filename   = 'tempfile.txt' 
       HeaderLines = 4
   end
   properties
       DataFormat = '%g' 
       Delimiter = ',' 
       SamplesPerFrame = 1024
       PlayCount = 1
   end

Частная собственность

Частная собственность не видны пользователю и могут служить ряду целей, включая

  • Чтобы удерживать значения, вычисленные только иногда, затем используется с последующими вызовами алгоритма. Для примера значения, используемые во время инициализации, когда setup вызывается или объект вызывается впервые. Это может сэкономить их перевычисление во время выполнения и улучшить эффективность основных функциональных возможностей

  • Чтобы определить внутреннее состояние объекта. Для примера, pNumEofReached хранит количество раз, когда был достигнут индикатор конца файла:

   properties(Access = private)
       pFID = -1 
       pNumChannels 
       pLineFormat 
       pNumEofReached = 0
   end

Конструктор

Конструктор определен так, чтобы можно было создать TextFileReader объект использует пары "имя-значение". Конструктор вызывается, когда новый образец TextDataReader создается. Вызов setProperties в конструкторе позволяет устанавливать свойства с парами "имя-значение" при конструкции. В конструкторе не должны задаваться другие задачи инициализации. Вместо этого используйте setupImpl способ.

   methods
       function obj = TextFileReader(varargin)
           setProperties(obj, nargin, varargin{:});
       end
   end

Переопределяющие matlab.System Методы, защищенные базовым классом

Каждый из общедоступных методов, общих для всех системных объектов, имеет соответствующие защищенные методы, которые они вызывают внутренне. Имена этих защищенных методов все включают в себя Impl постфикс. Они могут быть реализованы при определении класса, чтобы запрограммировать поведение вашего системного объекта.

Для получения дополнительной информации о соответствии между стандартными открытыми методами и их внутренними реализациями см. Сводные данные последовательности вызовов.

Для примера, TextFileReader переопределяет эти Impl методы:

  • setupImpl

  • resetImpl

  • stepImpl

  • releaseImpl

  • isDoneImpl

  • processTunedPropertiesImpl

  • loadObjectImpl

  • saveObjectImpl

Частные методы

Частные методы доступны только из других методов того же класса. Они могут использоваться, чтобы сделать остальную часть кода более читаемой. Они также могут улучшить переиспользуемость кода путем группировки под отдельным кодом стандартных программ, который используется несколько раз в различных частях класса. Для TextFileReader, частные методы создаются для:

  • getWorkingFID

  • goToStartOfData

  • peekCurrentLine

  • lockNumberOfChannelsUsingCurrentLine

  • readNDataRows

Запись и чтение данных

В этом примере показано, как вы можете использовать TextFileReader и TextFileWriter около:

  • Создание текстового файла, содержащего выборки двух различных синусоидальных сигналов с помощью TextFileWriter

  • Чтение из текстового файла осуществляется с помощью TextFileReader.

Создайте простой текстовый файл

Создайте новый файл для хранения двух синусоидальных сигналов с частотами 50 Гц и 60 Гц. Для каждого сигнала сохраненные данные состоят из 800 выборок со частотой дискретизации 8 кГц.

Создайте выборки данных:

fs = 8000;
tmax = 0.1;
t = (0:1/fs:tmax-1/fs)';
N = length(t);
f = [50,60];
data = sin(2*pi*t*f);

Сформируйте строку заголовка, чтобы описать данные читаемым способом для будущего использования (необязательный шаг):

fileheader = sprintf(['The following contains %d samples of two ',...
    'sinusoids,\nwith frequencies %d Hz and %d Hz and a sample rate of',...
    ' %d kHz\n\n'], N, f(1),f(2),fs/1000);

Чтобы сохранить сигнал в текстовый файл, создайте TextFileWriter объект. Конструктор TextFileWriter необходимо имя целевого файла и некоторые необязательные параметры, которые могут быть переданы в виде пар "имя-значение".

TxtWriter = TextFileWriter('Filename','sinewaves.txt','Header',fileheader)
TxtWriter = 
  TextFileWriter with properties:

      Filename: 'sinewaves.txt'
        Header: 'The following contains 800 samples of two sinusoids,...'
    DataFormat: '%.18g'
     Delimiter: ','

TextFileWriter записывает данные в разделенные разделителем ASCII-файлы. Его общественная собственность включают:

  • Filename - Имя файла, который будет записан. Если файл с таким именем уже существует, он перезаписывается. Когда начинаются операции, объект начинает запись в файл сразу после заголовка. Затем объект добавляет новые данные при каждом последующем вызове объекта, пока он не будет деблокирован. Выполнение сброса вызова возобновляет запись с начала файла.

  • Header - Символьная строка, часто состоящая из нескольких линий и заканчиваемая символом newline (\n). Это задается пользователем и может быть изменено для встраивания считываемой человеком информации, которая описывает фактические данные.

  • DataFormat - Формат, используемый для хранения каждой выборки данных. Это может взять любое значение, присваиваемое в качестве спецификатора преобразования в formatSpec строка, используемая встроенной функцией MATLAB fprintf. DataFormat применяется ко всем каналам, записанным в файл. Значение по умолчанию для этого свойства '%.18g', что позволяет сохранить данные двойной точности с плавающей точкой в полной точности.

  • Delimiter - Символ, используемый для разделения выборок из различных каналов одновременно. Каждая линия написанного файла преобразуется в момент времени, и она включает в себя столько выборок, сколько предоставлено каналов в качестве входных (другими словами, количество столбцов в матричном входе, переданное объекту).

Чтобы записать все доступные данные в файл, можно использовать один вызов.

TxtWriter(data)

Деблокируйте управление файлом путем вызова release функция.

release(TxtWriter)

Теперь данные хранятся в новом файле. Чтобы визуально просмотреть файл, введите:

edit('sinewaves.txt')

Поскольку заголовок занимает три линии, данные начинаются в линии 4.

В этом простом случае длина всего сигнала небольшая, и он удобно помещается на системной памяти. Поэтому данные можно создать все сразу и записать в файл за один шаг.

Бывают случаи, когда такой подход невозможен или практичен. Для примера данные могут быть слишком большими, чтобы помещаться в один Переменный MATLAB (слишком большими, чтобы помещаться в системной памяти). В качестве альтернативы данные могут быть созданы циклически в цикле или переданы в MATLAB из внешнего источника. Во всех этих случаях потоковая передача данных в файл может быть выполнена с помощью подхода, аналогичного следующему примеру.

Используйте потоковый генератор синусоиды, чтобы создать систему координат данных по циклу. Запустите необходимое количество итераций, чтобы создать данные и сохранить их в файле:

frameLength = 32;
tmax = 10; 
t = (0:1/fs:tmax-1/fs)';
N = length(t);
data = sin(2*pi*t*f);
numCycles = N/frameLength;

for k = 1:10 % Long running loop when you replace 10 with numCycles. 
    dataFrame = sin(2*pi*t*f);
    TxtWriter(dataFrame)
end

release(TxtWriter)

Чтение из существующего текстового файла

Чтобы считать из текстового файла, создайте образец TextFileReader.

TxtReader = TextFileReader('Filename','sinewaves.txt','HeaderLines',3,'SamplesPerFrame',frameLength)
TxtReader = 
  TextFileReader with properties:

           Filename: 'sinewaves.txt'
        HeaderLines: 3
         DataFormat: '%g'
          Delimiter: ','
    SamplesPerFrame: 32
          PlayCount: 1

TextFileReader считывает числовые данные из ASCII-файлов, разделенных разделителями. Его свойства аналогичны свойствам TextFileWriter. Далее следуют некоторые различия

  • HeaderLines - Количество линий, используемых заголовком в файле, указанном в Filename. Первый вызов объекта начинает считываться с номера линии HeaderLines+1. Последующие вызовы объекта продолжают считываться из линии сразу после ранее считанной линии. Вызывающие reset возобновит чтение из линии HeaderLines+1.

  • Delimiter - Символ, используемый для разделения выборок из различных каналов одновременно. В этом случае разделитель также используется, чтобы определить количество каналов данных, хранящихся в файле. Когда объект запускается впервые, объект подсчитывает количество Delimiter символы в линии HeaderLines+1, скажем numDel. Затем для каждого момента времени объект читается numChan = numDel+1 числовые значения с форматированными DataFormat. Матрица, возвращенная алгоритмом, имеет размер SamplesPerFrame-by- numChan.

  • SamplesPerFrame - Количество строк, считанных каждым вызовом объекта. Это значение также является количеством строк матрицы, возвращенной в качестве вывода. При достижении последних доступных строк данных может быть меньше необходимого SamplesPerFrame. В этом случае доступные данные заполняются нулями, чтобы получить матрицу размера SamplesPerFrame-by- numChan. Когда все данные считываются, алгоритм просто возвращается zeros(SamplesPerFrame,numChan) до reset или release вызывается.

  • PlayCount - Количество циклических чтений данных в файле. Если объект достигает конца файла, и файл еще не был считан в несколько раз равным PlayCount, чтение возобновляется с начала данных (линия HeaderLines+1). Если последние линии файла не обеспечивают достаточное количество выборок, чтобы сформировать полную выходную матрицу размера SamplesPerFrame-by- numChan, затем система координат завершается с использованием начальных данных. После чтения файла PlayCount раз выходная матрица, возвращаемая алгоритмом, заполняется нулями, и все вызовы isDone возвращает true, если только reset или release вызывается. Чтобы просматривать доступные данные бессрочно, PlayCount может быть задано значение Inf.

Для чтения данных из текстового файла используется более общий потоковый подход. Этот способ чтения данных также имеет отношение к работе с очень большими файлами данных. Предварительно выделите систему координат данных с frameLength строки и 2 столбца.

dataFrame = zeros(frameLength,2,'single');

Чтение из текстового файла и запись в двоичный файл, пока данные присутствуют в исходном текстовом файле. Заметьте, как метод isDone используется для управления выполнением цикла while.

while(~isDone(TxtReader))
    dataFrame(:) = TxtReader();
end

release(TxtReader)

Сводные данные

Этот пример иллюстрировал, как создавать и использовать системные объекты для чтения и записи в файлы числовых данных. TextFileReader и TextFileWriter может редактироваться для выполнения специальных операций чтения и записи файлов. Можно также объединить эти пользовательские системные объекты со встроенными системными объектами, такими как dsp.BinaryFileWriter и dsp.BinaryFileReader.

Дополнительные сведения об авторских объектах System для пользовательских алгоритмов см. в разделе Создание системных объектов.

Похожие темы