【问题标题】:Continuously reading serial-port buffer and parsing data to array in C#在 C# 中连续读取串口缓冲区并将数据解析为数组
【发布时间】:2020-04-26 10:52:39
【问题描述】:

您好,我正在尝试寻找连续读取串行端口缓冲区并将数据解析为数组的最佳解决方案,连续字符串形式的串行端口如下所示:

"...G 130 克\r\nG 130 克\r\nG 124 克\r\nG 124 克\r\nG 124 g\r\nG..."

主要思想是从串口广播字符串中读取例如最后3个数据,解析为双数组[124.0; 124.0; 124.0],如果相等则比较。

现在我正在使用这个简单的代码,但速度不够快:

_serialPortMainForm.DataReceived += new SerialDataReceivedEventHandler(Port_DataReceived);

.....

void Port_DataReceived(object sender, SerialDataReceivedEventArgs e)
            {
                byte[] data = new byte[_serialPortMainForm.BytesToRead];
                _serialPortMainForm.Read(data, 0, data.Length);
                string str = Encoding.ASCII.GetString(data);
                RawSerialPortData += str;
                if (RawSerialPortData.Length > Properties.Settings.Default.BufferSize) {
                    ProcessSerialPortData(RawSerialPortData);
                    RawSerialPortData = "";
                }
            }

并像这样解析数据:

public void ProcessSerialPortData( string DataToProcess) {
            int count = 0;
            string PostFix = "";

            DataToProcess = DataToProcess.Substring(DataToProcess.IndexOf('G') + 1);
            DataToProcess = DataToProcess.Replace(" ", "");
            DataToProcess = DataToProcess.Replace(Environment.NewLine, "|");

            foreach (char c in DataToProcess) if (c == '|') count++;
            ProcessedData = new double[count-1];

            DataToProcess = DataToProcess.Replace("G", "");

            if (DataToProcess.Contains("kg")) { PostFix = "kg"; DataToProcess = DataToProcess.Replace("kg", ""); }
            if (DataToProcess.Contains("g")) { PostFix = "g"; DataToProcess = DataToProcess.Replace("g", ""); }

            UnitsController(PostFix);

            DataToProcess = DataToProcess.Replace(".", ",");
            string[] SplitData = DataToProcess.Split('|');

            int j = 0;
            while (j < count - 1) {

                Double.TryParse(SplitData[j], out ProcessedData[j]);
                j++;
            }
        }

公斤与这种情况无关,因为克对于这种情况就足够了

有什么想法或简单和最佳的解决方案如何更好更快地做到这一点?

【问题讨论】:

  • 我假设缓冲区大小足以容纳三个读数?
  • 另外,所有测量值是否总是相同的PostFix?或者它会因测量而异?
  • 缓冲区可容纳大约 10 个读数...来自串行端口的数据是流式的,只有数字是变化的,所有测量的后缀都相同..
  • 代码可以在没有任何问题的情况下工作,但我认为这不是从流中解析数据的最佳方式。因为如您所见,我在每个“Properties.Settings.Default.BufferSize”复制部分流,现在它设置为 100 ...
  • 我刚刚发布了一个答案。看一看。 :-)

标签: c# arrays parsing serial-port buffer


【解决方案1】:

对缓冲区中的字符串进行某些假设,可以使用正则表达式提取所有值。

在方法外部声明一个全局变量并编译正则表达式以获得更快的结果:

Regex _regex = new Regex(@"\d+\s+\w+", RegexOptions.Compiled);

然后在您的方法中,使用以下内容提取所有值:

var matches = _regex.Matches(DataToProcess)
    .Cast<Match>()
    .Select(m => 
    {
        var parts = m.Value.Split(' ');
        return new { Value = parts[0], Unit = parts[1] };
    });

//This is just for you to see the results in the console.
foreach (var value in matches)
{
    Console.WriteLine(value);
}

假设DataToProcess 包含这个:

var DataToProcess = @"G130 g\r\nG 130 g\r\nG 124 g\r\nG 124 g\r\nG 124 g\r\n";

这将在控制台中产生以下内容:

{ 值 = 130,单位 = g }

{ 值 = 130,单位 = g }

{ 值 = 124,单位 = g }

{ 值 = 124,单位 = g }

{ 值 = 124,单位 = g }

然后您可以使用此枚举来测试单位、值等。

如果您需要将值作为双精度数组,只需使用:

var ProcessedData = matches.Select(m => Convert.ToDouble(m.Value)).ToArray();

最后,camelCase 在 C# 中通常首选用于变量名称,而且您的代码似乎不是非常线程安全的。需要考虑的事情。

【讨论】:

  • 只有值就足够了,但是有可能将字符串值转换为双精度值数组...类似于... TryParse ??
  • @Oliwer11:当然。只需在最后一行添加一个转换。我会修改我的答案。
  • @Oliwer11:很高兴。 :-)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-05-18
  • 1970-01-01
  • 2011-11-14
  • 2023-03-03
  • 1970-01-01
相关资源
最近更新 更多