从串口解析/格式化数据 - C# [英] Parsing/formatting data from serial port - C#

查看:140
本文介绍了从串口解析/格式化数据 - C#的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经开发了一个小程序,监听到一个串行端口。我的程序正在接收数据。问题在于,其不以需要的格式(一个字符串)显示它。这些数据我的节目接收进来两个字符串,例如:

I've developed a small program that listens to a serial port. My program is receiving data. The problem is, its not displaying it in the desired format (one string). The data my program is receiving comes in two strings, for example:

ID:34242 State:NY

邮编:12345 StreetType:大道

Zip:12345 StreetType:Ave

它是由大块显示和一些数据传递到下一行作为这样的:

Its being displayed by chunks and some of the data is passed on to next lines as such:

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

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

I have used the SerialDataReceive Event Handler to receive my data and it looks like this:

 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(),但我的数据不会得到事件显示带有该功能。有谁知道任何其他方式来解析,数据格式为一个字符串?

As you can see, I retrieve the bytes into the buffer, create a byte array to hold the data and use ASCII encoding to translate the bytes into a string. I tried using ReadLine() but my data doesn't event get displayed with that function. Does anyone know of any other way to parse and format the data into one string?

推荐答案

的问题是,因为你可能有猜到,该事件DataReceived被尽快数据已被接收到的串行端口提出。可能没有有完整记录;该的SerialPort对象没有线索,你认为什么是足够的数据是显著,还是可行的。

The problem is, as you may have guessed, that the event DataReceived is raised as soon as data has been received over the serial port. There may not be a complete record there; the SerialPort object has no clue what you consider to be "enough" data to be significant, or workable.

通常的解决办法是保持接收数据的另一种缓冲 ,包含你已经认识到不完整的数据。当数据来自于通过端口和事件触发时,应首先考虑什么是在缓冲区并追加到您已经收到了什么。然后,你应该开始在这个数据缓冲区的开头,检查接收到的数据,寻找原子已经意味着你的数据块已知模式;例如,假设你收到的第一件事就是编号:12。你拿着这个,把它放在缓冲区中,然后扫描缓冲区找一个正则表达式定义图案ID:\d *。因为尾随空格没有出现在你的缓冲区,你的模式无法找到有意义的事,所以你现在知道你有没有收到一个完整的邮件。

The usual solution is to maintain another "buffer" of received data, containing any data you have recognized as incomplete. When data comes in over the port and your event fires, it should first take what's in the buffer and append it to what you have already received. Then, you should start at the beginning of this data buffer and inspect the received data, looking for known patterns of atomic "chunks" of data that have meaning to you; for instance, say the first thing you receive is "ID: 12". You take this, put it in the buffer, then scan the buffer looking for a pattern defined by a regex "ID: \d*? ". Because the trailing space is not present in your buffer, your pattern fails to find anything of meaning, and so you now know you haven't received a full message.

然后,在DataReceived事件检索下一个认识,你拉453站出串行缓冲器。您将其追加到你已经拥有并获得ID:12453站,当你使用正则表达式,你得到的比赛ID:12345。您传递到这一点作进一步处理的方法(显示控制台,也许),并从缓冲区的前面取出相同的字符串,留下站。扫描一次你没有找到任何东西的兴趣,所以你离开你所拥有的,循环重复AWS数据继续进来显然,你将测试不仅仅是ID模式更多的模式。你可以搜索整个字符串您希望收到,如ID:\d *州:\w {2}。你甚至可以保持数据在缓冲区,直到你有一个记录两个字符串:ID:\d *州:\w {2}邮编:\d {5} StreetType: \w *?

Then, on the next raising of the DataReceived event, you pull "453 Sta" out of the serial buffer. You append it to what you already have and get "ID:12453 Sta", and when you apply the regex, you get the match "ID: 12345 ". You pass this into a method for further processing (display to the console, maybe), and remove the same string from the front of the buffer, leaving "Sta". Scanning again you don't find anything else of interest, so you leave what you have, and the cycle repeats aws data continues to come in. Obviously, you'll be testing more patterns than just the ID pattern; you may search for an entire "string" you expect to receive, such as "ID: \d*? State: \w{2} ". You may even keep the data in your buffer until you have both strings for a record: "ID:\d*? State:\w{2} Zip:\d{5} StreetType:\w*? ".

无论哪种方式,你需要确定是否接收到的数据是不是可靠的固定长度(意为某一特定类型的每个字符串将始终具有相同数量的字节或字符)的,或可靠地分隔(意会有一些字符或字符组合总是分离数据的显著元素)。如果这些都不适用,它可能是非常困难的分析数据为单场块

Either way, you will need to identify whether the data being received is either reliably "fixed-length" (meaning each string of a particular type will always have the same number of bytes or characters), or reliably "delimited" (meaning there will be some character or character combination that always separates significant elements of data). If neither of these apply, it may be very difficult to parse the data into single-field chunks.

下面是根据你所拥有的已经是一个示例:

Here's a sample based on what you have already:

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#的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆