我正在尝试找到一种很好的方法将数据从NetworkStream(通过C#)写入文本文件,同时“准同时”将新写入的数据从文本文件读入Matlab。
基本上,是否存在用于协调写/读操作(来自单独的程序)的良好方法或技术,使得读操作不会阻止写操作(反之亦然)并且连续写/读之间的延迟被最小化?
目前我只是通过WriteLine循环将数据从网络流写入(附加)到文本文件,并通过循环Matlab的fscanf函数读取数据,该函数还标记最后读取的元素并将文件指针重新定位到该位置。
C#代码的相关部分:
(注意:我正在使用的循环条件是任意的,我只是想看看现在有什么用。)
NetworkStream network_stream = tcp_client.GetStream();
string path = @"C:\Matlab\serial_data.txt";
FileInfo file_info = new FileInfo(path);
using (StreamWriter writer = file_info.CreateText())
{
string foo = "";
writer.WriteLine(foo);
}
using (StreamWriter writer = File.AppendText(path))
{
byte[] buffer = new byte[1];
int maxlines = 100000;
int lines = 0;
while (lines <= maxlines)
{
network_stream.Read(buffer, 0, buffer.Length);
byte byte2string = buffer[0];
writer.WriteLine(byte2string);
lines++;
}
}
相关的Matlab代码:
i=0;
while i<100;
a = fopen('serial_data.txt');
b = fscanf(a, '%g', [1000 1]);
fclose(a);
i=i+1;
end
当我查看读入Matlab的数据时,实际数据之间存在大量的零,而最令人不安的部分是在这些“假零”延伸之间读取的连续数据点的数量变化很大。
我正在考虑尝试将一些延迟(Thread.sleep和wait(timerObject))分别插入到C#和Matlab中,但即便如此,我也不相信会保证我总是获得通过网络流,这是必要的。
非常感谢任何建议/建议。
答案 0 :(得分:1)
看起来在Matlab方面的阅读器中使用fscanf
的方式存在问题。
读者代码看起来每次都会重复读取整个文件,因为它会在每次循环中重新打开它。这是故意的吗?如果要跟踪文件的结尾,您可能希望保持文件句柄处于打开状态,并且只需检查是否可以通过在同一个打开的文件句柄上重复fscanf
次调用来从中读取更多数据。 / p>
此外,fscanf
调用看起来总是返回一个零填充的1000元素数组,无论它读取的文件有多大。也许这就是你的“假零”来自哪里。有多少会因文件中实际存在多少数据以及Matlab代码在写入之间读取它的频率而有所不同。抓住fscanf
的第二个argout,看看它实际读取了多少元素。
[b,nRead] = fscanf(a, '%g', [1000 1]);
fprintf('Read %d numbers\n', nRead);
b = b(1:nRead);
检查doc page for fscanf
。在“输出参数”部分中:“如果输入包含少于sizeA的元素,则MATLAB®会用零填充A.”
然后你可能想看看这个问题:How can I do an atomic write/append in C#, or how do I get files opened with the FILE_APPEND_DATA flag?。保持写入比输出流的缓冲区更短(就像它们现在一样)将使它们成为原子,并且在每次写入后刷新将使读者及时看到它们。