В этом примере показано, как создавать и использовать два различных системных объекта для упрощения потоковой передачи данных в MATLAB ® и из него :TextFileReader и TextFileWriter.
Объекты, рассмотренные в этом примере, относятся к нескольким реалистическим сценариям использования и могут быть настроены для выполнения более сложных и специализированных задач.
Системные объекты являются классами MATLAB, производными от matlab.System. В результате все объекты системы наследуют общий открытый интерфейс, который включает стандартные методы:
setup - инициализация объекта, как правило, в начале моделирования;
reset - очистить внутреннее состояние объекта, вернув его в статус по умолчанию после инициализации;
release - Высвобождение любых ресурсов (памяти, оборудования или ресурсов, специфичных для ОС), используемых внутри объекта
При создании новых видов системных объектов предоставляются специальные реализации для всех предшествующих методов, чтобы определить их поведение.
В этом примере рассматривается внутренняя структура и использование следующих двух системных объектов:
TextFileReader
TextFileWriter
Для создания этих системных объектов для потоковой передачи данных в MATLAB и из MATLAB в этом примере используются стандартные низкоуровневые файловые функции ввода-вывода, доступные в MATLAB (например, fscanf, fread, fprintf, и fwrite). Абстрагируя большинство деталей использования этих функций, они стремятся сделать задачу чтения и записи потоковых данных более простой и эффективной.
Этот пример включает использование ряда расширенных конструкций для создания системных объектов. Более общие сведения о разработке системных объектов см. в разделе Создание системных объектов.
TextFileReader TextFileReader класс включает определение класса, общие и частные свойства, конструктор, защищенные методы, переопределенные из matlab.System базовый класс и частные методы. TextFileWriter класс имеет аналогичную структуру.
Определение класса указывает, что TextFileReader класс является производным от обоих matlab.System и matlab.system.mixin.FiniteSource.
classdef (StrictDefaults)TextFileReader < matlab.System & matlab.system.mixin.FiniteSource
matlab.System является обязательным и является базовым классом для всех системных объектов
matlab.system.mixin.FiniteSource указывает, что этот класс является источником сигнала с конечным числом выборок данных. Для этого типа класса, в дополнение к обычному интерфейсу, объект System также предоставляет 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 постфикс. Они могут быть реализованы при определении класса для программирования поведения объекта System.
Для получения дополнительной информации о соответствии между стандартными общедоступными методами и их внутренними реализациями см. раздел Сводка последовательности вызовов.
Например, 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 - имя записываемого файла. Если файл с таким именем уже существует, он перезаписывается. При запуске операций объект начинает запись в файл сразу после заголовка. Затем объект добавляет новые данные при каждом последующем вызове объекта до тех пор, пока он не будет освобожден. Вызов reset возобновляет запись с начала файла.
Header - символьная строка, часто состоящая из нескольких строк и заканчивающаяся символом новой строки (\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около-numChan.
SamplesPerFrame - Количество строк, считываемых каждым вызовом объекта. Это значение также является количеством строк матрицы, возвращаемых в качестве выходных данных. При достижении последних доступных строк данных их может быть меньше требуемого SamplesPerFrame. В этом случае доступные данные дополняются нулями для получения матрицы размера SamplesPerFrameоколо-numChan. Как только все данные считаны, алгоритм просто возвращает zeros(SamplesPerFrame,numChan) до reset или release вызывается.
PlayCount - Число циклических считываний данных в файле. Если объект достигает конца файла и файл еще не прочитан, количество раз равно PlayCount, чтение возобновляется с начала данных (строка HeaderLines+1). Если в последних строках файла недостаточно образцов для формирования полной выходной матрицы размера SamplesPerFrameоколо-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.
Дополнительные сведения о создании системных объектов для пользовательских алгоритмов см. в разделе Создание системных объектов.