C#连续读取串口缓冲区并解析数据到数组
Continuously reading serial-port buffer and parsing data to array in C#
你好,我正在尝试寻找连续读取串口缓冲区并将数据解析为数组的最佳解决方案,连续字符串形式的串口如下所示:
"...G 130 g\r\nG 130 g\r\nG 124 g\r\nG 124 g\r\nG 124
g\r\nG... "
主要思路是从串口广播字符串中读取最后3个数据,解析为double数组[124.0; 124.0; 124.0] 和 comapre 如果等于。
现在我正在使用这个简单的代码,但速度不够快:
_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++;
}
}
公斤与这种情况无关,因为克对于这种情况已经足够
有没有人有任何想法或简单且最佳的解决方案如何更好更快地做到这一点??
对缓冲区中的字符串做出某些假设,可以使用 Regex 提取所有值。
在方法外声明一个全局变量并编译 Regex 以获得更快的结果:
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";
这将在控制台中产生以下内容:
{ Value = 130, Unit = g }
{ Value = 130, Unit = g }
{ Value = 124, Unit = g }
{ Value = 124, Unit = g }
{ Value = 124, Unit = g }
然后您可以使用此枚举来测试单位、值等。
如果您需要双精度数组形式的值,只需使用:
var ProcessedData = matches.Select(m => Convert.ToDouble(m.Value)).ToArray();
最后,camelCase 在 C# 中通常是变量名的首选,您的代码似乎不是线程安全的。需要考虑的事情。
你好,我正在尝试寻找连续读取串口缓冲区并将数据解析为数组的最佳解决方案,连续字符串形式的串口如下所示:
"...G 130 g\r\nG 130 g\r\nG 124 g\r\nG 124 g\r\nG 124 g\r\nG... "
主要思路是从串口广播字符串中读取最后3个数据,解析为double数组[124.0; 124.0; 124.0] 和 comapre 如果等于。
现在我正在使用这个简单的代码,但速度不够快:
_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++;
}
}
公斤与这种情况无关,因为克对于这种情况已经足够
有没有人有任何想法或简单且最佳的解决方案如何更好更快地做到这一点??
对缓冲区中的字符串做出某些假设,可以使用 Regex 提取所有值。
在方法外声明一个全局变量并编译 Regex 以获得更快的结果:
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";
这将在控制台中产生以下内容:
{ Value = 130, Unit = g }
{ Value = 130, Unit = g }
{ Value = 124, Unit = g }
{ Value = 124, Unit = g }
{ Value = 124, Unit = g }
然后您可以使用此枚举来测试单位、值等。
如果您需要双精度数组形式的值,只需使用:
var ProcessedData = matches.Select(m => Convert.ToDouble(m.Value)).ToArray();
最后,camelCase 在 C# 中通常是变量名的首选,您的代码似乎不是线程安全的。需要考虑的事情。