这个例子展示了如何创建和使用两个不同的System对象,以促进数据流进出MATLAB®:TextFileReader
和TextFileWriter
.
本例中讨论的对象解决了许多现实的用例,可以对它们进行定制,以实现更高级和专门的任务。
系统对象是派生自的MATLAB类matlab。系统
.因此,系统对象都继承一个公共的公共接口,其中包括标准方法:
设置
-初始化对象,通常在模拟的开始
重置
-清除对象的内部状态,使其恢复到初始化后的默认状态
释放
释放对象内部使用的任何资源(内存、硬件或特定于操作系统的资源)
当您创建新的System对象类型时,您将为所有上述方法提供特定的实现,以确定其行为。
在这个例子中,我们将讨论以下两个System对象的内部结构和使用:
TextFileReader
TextFileWriter
为了创建用于进出MATLAB的流数据的System对象,本例使用了MATLAB中可用的标准低级文件I/O函数(例如fscanf
,从文件中读
,流
,写入文件
).通过抽象这些函数的大部分使用细节,它们旨在使读写流数据的任务更简单、更高效。
这个示例包括使用许多高级构造来创建System对象。有关创建System对象的更基本介绍,请参见创建系统对象.
TextFileReader
的TextFileReader
类包含类定义、公共和私有属性、构造函数、从matlab。系统
基类和私有方法。的TextFileWriter
类的结构类似。
类定义声明TextFileReader
类是由两者派生的matlab。系统
和matlab.system.mixin.FiniteSource
.
TextFileReader < matlab. classdef (StrictDefaults)系统& matlab.system.mixin.FiniteSource
matlab。系统
是必需的,基类是否适用于所有System对象
matlab.system.mixin.FiniteSource
表示该类是具有有限数量数据样本的信号源。对于这种类型的类,除了通常的接口外,System对象还将公开结束
函数。当结束
返回true,表示该对象已到达可用数据的末尾。
用户可以修改公共属性,以调整其特定应用程序的对象行为。TextFileReader
有两个不可调优的公共属性(它们只能在第一次调用对象之前更改)和四个可调优的公共属性。所有公共属性都有一个默认值。当用户没有指定其他属性时,会将默认值分配给相应的属性。
属性(不可调优)Filename = 'tempfile.txt' HeaderLines = 4结束
'%g' Delimiter = ',' SamplesPerFrame = 1024 PlayCount = 1 end . properties数据格式= '%g' Delimiter = ',' SamplesPerFrame = 1024 PlayCount = 1 end . properties
私有属性对用户是不可见的,可以用于许多目的,包括
保存偶尔计算的值,然后在后续对算法的调用中使用。例如,当初始化时使用的值设置
或对象第一次被调用。这可以节省在运行时重新计算它们的时间,并提高核心功能的性能
定义对象的内部状态。例如,pNumEofReached
存储到达文件结束符指示符的次数:
pFID = -1 pNumChannels pLineFormat pnummeofreached = 0 end . properties(Access = private) pFID = -1 pNumChannels pLineFormat pnummeofreached = 0
定义了构造函数,以便您可以构造TextFileReader
使用名称-值对的对象。的新实例时调用构造函数TextDataReader
被创建。调用找
在构造函数内部,允许在构造时使用名称-值对设置属性。不应该在构造函数中指定其他初始化任务。相反,使用setupImpl
方法。
方法obj = TextFileReader(varargin) setProperties(obj, nargin, varargin{:});结束结束
matlab。系统
基类保护方法所有System对象的公共方法都有相应的内部调用的受保护方法。这些受保护方法的名称都包含Impl
后缀。它们可以在定义类以对System对象的行为进行编程时实现。
有关标准公共方法及其内部实现之间的通信的更多信息,请参阅呼叫序列摘要.
例如,TextFileReader
覆盖这些Impl
方法:
setupImpl
resetImpl
stepImpl
releaseImpl
isDoneImpl
processTunedPropertiesImpl
loadObjectImpl
saveObjectImpl
私有方法只能从同一类的其他方法中访问。它们可以用来使其余的代码更具可读性。通过将在类的不同部分中多次使用的代码分组到单独的例程中,它们还可以提高代码的可重用性。为TextFileReader
,私有方法被创建为:
getWorkingFID
goToStartOfData
peekCurrentLine
lockNumberOfChannelsUsingCurrentLine
readNDataRows
这个例子展示了如何使用TextFileReader
和TextFileWriter
由:
使用。创建包含两个不同正弦信号样本的文本文件TextFileWriter
使用从文本文件读取TextFileReader
.
创建一个新文件来存储两个频率为50hz和60hz的正弦信号。对于每个信号,存储的数据由800个采样组成,采样率为8khz。
创建数据样本:
fs = 8000;达峰时间= 0.1;t = (0:1 / fs: tmax-1 / fs) ';N =长度(t);f =(50、60);data =罪(2 *π* t * f);
形成一个头字符串,以一种可读的方式描述数据,以便将来使用(可选步骤):
fileheader = sprintf (['下面包含%d个样本',...正弦波,频率为%d Hz和%d Hz,采样率为,...“% d千赫\ n \ n”f)、N、f (1), (2), fs / 1000);
若要将信号存储到文本文件中,请创建TextFileWriter
对象。的构造函数TextFileWriter
需要目标文件的名称和一些可选参数,这些参数可以作为名称-值对传入。
TxtWriter = TextFileWriter (“文件名”,“sinewaves.txt”,“头”fileheader)
TxtWriter = TextFileWriter with properties: Filename: ' sininewaves .txt' Header: 'The following contains 800 samples of two sinusoids,…'DataFormat:“%。分隔符:18 g”、“
TextFileWriter
将数据写入分隔符分隔的ASCII文件。其公共财产包括:
文件名
—待写入的文件名。如果已经存在具有此名称的文件,则会覆盖该文件。当操作开始时,对象立即在头文件之后开始写入文件。然后,对象在每次后续调用时都追加新的数据,直到对象被释放为止。调用reset将恢复从文件开始的写入。
头
-字符串,通常由多行组成,以换行符结尾(\ n
).这是由用户指定的,可以修改以嵌入人类可读的描述实际数据的信息。
DataFormat
—存储每个数据样本的格式。可以将任何可分配的值作为转换说明符formatSpec
使用MATLAB内置的字符串函数流
.DataFormat
适用于写入文件的所有通道。此属性的默认值是“% .18g”
,允许以完全精度保存双精度浮点数据。
分隔符
-字符用于在同一时刻从不同的通道分离样本。写入文件的每一行都映射到一个时间瞬间,它包含的样本与作为输入提供的通道的数量一样多(换句话说,传递给对象的矩阵输入的列的数量)。
要将所有可用数据写入文件,可以使用单个的To调用。
TxtWriter(数据)
的方法释放对文件的控制释放
函数。
发行版(TxtWriter)
数据现在存储在新文件中。要直观地检查文件,输入:
编辑(“sinewaves.txt”)
因为头文件占了三行,所以数据从行开始4
.
在这种简单的情况下,整个信号的长度很小,它适合于系统内存。因此,可以一次性创建所有数据,并在单个步骤中将其写入文件。
在某些情况下,这种方法是不可能或不实际的。例如,数据可能太大而无法放入单个MATLAB变量(太大而无法放入系统内存)。或者,数据可以在循环中循环创建,或者从外部源流到MATLAB。在所有这些情况下,可以使用与下面示例类似的方法将数据流导入文件。
使用流正弦波发生器在每个循环中创建一帧数据。运行所需的迭代次数来创建数据并将其存储到文件中:
frameLength = 32;达峰时间= 10;t = (0:1 / fs: tmax-1 / fs) ';N =长度(t);data =罪(2 *π* t * f);numCycles = N / frameLength;为k = 1:10当你用numCycles替换10时,长循环。dataFrame =罪(2 *π* t * f);TxtWriter (dataFrame)结束发行版(TxtWriter)
要从文本文件中读取,请创建TextFileReader
.
TxtReader = TextFileReader (“文件名”,“sinewaves.txt”,“HeaderLines”3,“SamplesPerFrame”frameLength)
TxtReader = TextFileReader与属性:Filename: 'sinewaves.txt' HeaderLines: 3 DataFormat: '%g' Delimiter: ',' SamplesPerFrame: 32 PlayCount: 1
TextFileReader
从分隔符分隔的ASCII文件中读取数字数据。它的性质类似于TextFileWriter
.遵循的一些差异
HeaderLines
-文件中指定的头文件使用的行数文件名
.对对象的第一次调用从行号开始读取HeaderLines + 1
.对该对象的后续调用将继续从紧挨着前一个读取行的行中读取。调用重置
将从一行开始重新阅读HeaderLines + 1
.
分隔符
-字符用于在同一时刻从不同的通道分离样本。在本例中,分隔符还用于确定存储在文件中的数据通道的数量。当对象第一次运行时,对象计数分隔符
行字符HeaderLines + 1
说,numDel
.然后,对于每一个瞬间,对象读取numChan = numDel + 1
带格式的数值DataFormat
.算法返回的矩阵有大小SamplesPerFrame
——- - - - - -numChan
.
SamplesPerFrame
-每次调用对象读取的行数。这个值也是作为输出返回的矩阵的行数。当到达最后一个可用数据行时,数据行可能少于所需的数据行SamplesPerFrame
.在这种情况下,可用数据被填充为0以获得一个大小矩阵SamplesPerFrame
——- - - - - -numChan
.一旦读取了所有的数据,算法就会简单地返回0 (SamplesPerFrame numChan)
直到重置
或释放
被称为。
PlayCount
—循环读取文件数据的次数。如果对象到达文件的末尾,并且文件还没有被读取的次数等于PlayCount
,从数据(行)开始阅读简历HeaderLines + 1
).如果文件的最后几行没有提供足够的样本来形成一个完整的大小的输出矩阵SamplesPerFrame
——- - - - - -numChan
,然后使用初始数据完成帧。一旦文件被读取PlayCount
时,算法返回的输出矩阵为零,所有调用结束
返回true,除非重置
或释放
被称为。要对可用数据进行无限循环,PlayCount
可设置为正
.
要从文本文件读取数据,可以使用更通用的流方法。这种读取数据的方法也适用于处理非常大的数据文件。预分配数据帧frameLength
行和两列。
dataFrame = 0 (frameLength 2“单一”);
当源文本文件中存在数据时,从文本文件读取并写入二进制文件。注意这个方法结束
用于控制while循环的执行。
而(~isDone(TxtReader)) dataFrame(:) = TxtReader();结束发行版(TxtReader)
这个示例演示了如何编写和使用System对象从数字数据文件读取和写入数据文件。TextFileReader
和TextFileWriter
可编辑执行特殊用途的文件读写操作。您还可以将这些定制的System对象与内置的System对象组合起来,例如dsp。BinaryFileWriter
和dsp。BinaryFileReader
.
有关为自定义算法创建System对象的更多信息,请参见创建系统对象.