c# - 从串口解析/格式化数据 - C#

标签 c# serial-port

我开发了一个监听串口的小程序。我的程序正在接收数据。问题是,它没有以所需的格式(一个字符串)显示它。我的程序接收的数据有两个字符串,例如:

ID:34242 State:NY

zip :12345 StreetType:Ave

它由 block 显示,一些数据被传递到下一行:

 ID:34242
State:N
Y Zip:12
345 Street
Type:Ave

我已经使用 SerialDataReceive 事件处理程序来接收我的数据,它看起来像这样:

 private static void Port_DataReceived(object sender, SerialDataReceivedEventArgs e)
    {

        SerialPort spL = (SerialPort) sender;
        int bufSize = 20;
        Byte[] dataBuffer = new Byte[bufSize];
        Console.WriteLine("Data Received at"+DateTime.Now);
        Console.WriteLine(spL.Read(dataBuffer, 0, bufSize));
        string s = System.Text.ASCIIEncoding.ASCII.GetString(dataBuffer);
        Console.WriteLine(s);



    }

如您所见,我将字节检索到缓冲区中,创建一个字节数组来保存数据并使用 ASCII 编码将字节转换为字符串。我尝试使用 ReadLine(),但我的数据没有使用该函数显示。有谁知道将数据解析和格式化为一个字符串的任何其他方法?

最佳答案

问题是,正如您可能已经猜到的那样,一旦通过串行端口接收到数据,就会引发事件 DataReceived。那里可能没有完整的记录; SerialPort 对象不知道什么是您认为“足够”的数据是重要的或可行的。

通常的解决方案是维护接收数据的另一个“缓冲区”,其中包含您认为不完整的任何数据。当数据通过端口进入并且您的事件触发时,它应该首先获取缓冲区中的内容并将其附加到您已经收到的内容中。然后,您应该从这个数据缓冲区的开头开始检查接收到的数据,寻找对您有意义的已知数据原子“ block ”模式;例如,假设您收到的第一件事是 "ID: 12"。您将其放入缓冲区,然后扫描缓冲区以查找由正则表达式 "ID:\d*? " 定义的模式。因为尾随空格不存在于您的缓冲区中,您的模式无法找到任何有意义的内容,因此您现在知道您没有收到完整的消息。

然后,在下一次引发 DataReceived 事件时,您将 "453 Sta" 从串行缓冲区中拉出。您将它附加到您已有的内容上并获得 "ID:12453 Sta",当您应用正则表达式时,您将获得匹配项“ID: 12345”。您将其传递给进一步处理的方法(可能显示到控制台),并从缓冲区的前面删除相同的字符串,留下“Sta”。再次扫描你没有发现任何其他感兴趣的东西,所以你留下你拥有的,并且循环重复 aws 数据继续进来。显然,你将测试更多的模式,而不仅仅是 ID 模式;您可以搜索您希望收到的整个“字符串”,例如 "ID:\d*? State:\w{2} "。您甚至可以将数据保存在缓冲区中,直到您拥有两个字符串作为记录:"ID:\d*?State:\w{2} Zip:\d{5} StreetType:\w*?"

无论哪种方式,您都需要确定接收到的数据是可靠的“固定长度”(意味着特定类型的每个字符串将始终具有相同数量的字节或字符),还是可靠地“定界”(这意味着会有一些字符或字符组合始终分隔数据的重要元素)。如果这些都不适用,则可能很难将数据解析为单字段 block 。

这是一个基于您已有的示例:

private static StringBuilder receiveBuffer = new StringBuilder();

private static void Port_DataReceived(object sender, SerialDataReceivedEventArgs e)
{

    SerialPort spL = (SerialPort) sender;
    int bufSize = 20;
    Byte[] dataBuffer = new Byte[bufSize];
    Console.WriteLine("Data Received at"+DateTime.Now);
    Console.WriteLine(spL.Read(dataBuffer, 0, bufSize));
    string s = System.Text.ASCIIEncoding.ASCII.GetString(dataBuffer);
    //here's the difference; append what you have to the buffer, then check it front-to-back
    //for known patterns indicating fields
    receiveBuffer.Append(s);

    var regex = new Regex(@"(ID:\d*? State:\w{2} Zip:\d{5} StreetType:\w*? )");
    Match match;
    do{
       match = regex.Match(receiveBuffer.ToString());
       if(match.Success)
       {
          //"Process" the significant chunk of data
          Console.WriteLine(match.Captures[0].Value);
          //remove what we've processed from the StringBuilder.
          receiveBuffer.Remove(match.Captures[0].Index, match.Captures[0].Length);
       }
    } while (match.Success);
}

关于c# - 从串口解析/格式化数据 - C#,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9505197/

相关文章:

c# - 一种在监 window 口中获取对象并将其设为 "Script"的方法

c# - 从 x509Certificate2 启动 RSACryptoServiceProvider 的最佳方式?

c - 查找可用端口以使用 BSD 打开伪终端

linux - 使用 picocom - 发送请求

C# Emgu.Cv wrapper : Retrieved (byte) pixel-values of Mat do not match Image<Gray, byte> 字节值,裁剪 ROI 时

c# - 从 Rectangle.Intersects() 获取碰撞细节

c# - 我找不到 : System. 事务命名空间

c++ - 使用boost asio从串口读取最新数据

python - 从 Raspberry pi 发送串行通信

.net - 是否有 timeBeginPeriod 和 timeEndPeriod 方法的 .NET 替代品?