【问题标题】:How to optimize "real-time" C# write-to-file & MATLAB read-from-file operation如何优化“实时”C# 写入文件和 MATLAB 从文件读取操作
【发布时间】:2013-04-14 18:44:36
【问题描述】:

我正在尝试找到一种将数据从 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 的数据时,实际数据之间存在大量零,最令人不安的部分是在这些“假零”延伸之间读取的连续数据点的数量变化很大。

我正在考虑尝试分别在 C# 和 Matlab 中插入一些延迟(Thread.sleep 和 wait(timerObject)),但即便如此,我也不确信这能保证我始终获得通过网络流,这是必不可少的。

任何意见/建议将不胜感激。

【问题讨论】:

    标签: c# matlab optimization asynchronous read-write


    【解决方案1】:

    看起来fscanf 在 Matlab 端的阅读器中的使用方式存在问题。

    阅读器代码看起来每次循环都会重新读取整个文件,因为它会在每次循环时重新打开它。这是故意的吗?如果您想跟踪文件的结尾,您可能希望保持文件句柄打开,并继续检查是否可以通过在同一个打开的文件句柄上重复调用 fscanf 来从中读取更多数据。

    此外,fscanf 调用看起来可能总是返回一个零填充的 1000 元素数组,无论它读取的文件有多大。也许这就是你的“假零”的来源。有多少会因文件中实际有多少数据以及 Matlab 代码在两次写入之间读取它的频率而异。获取fscanf 的第二个参数,看看它实际读取了多少元素。

    [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?。保持写入比输出流的缓冲区短(就像现在一样)将使它们成为原子,并且在每次写入后刷新将使它们及时对读者可见。

    【讨论】:

    • 没有隐式转换到char类型,但是有一个从byte到int。未经测试,但根据该逻辑,您将获得 WriteLine(Int32) 调用。
    • 好的,这意味着这不是我在第一段中认为的转换问题;可能只是 fscanf 使用问题。
    • @Voo: 删除了关于 byte -> int32 vs char 转换的内容。
    • @Andrew:感谢您的输入-事实证明 StreamWritter.WriteLine() 隐式地将字节类型转换为字符串。我预计必须进行显式转换,因此用词不当 byte2string 变量(抱歉有任何混淆)。据我所知,C# 代码可以毫无问题地写出文本文件。这是一个心电图波形,如果我随后通过 Matlab 绘制文本文件数据,我可以看出存在间隙/不正确的转换。
    • 好的。是的,这听起来可能是fscanf 零填充并每次都重新读取整个文件。我稍微编辑了我的答案以扩展它;再看看。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多