将流式十六进制字符串拆分为较小的块

时间:2016-08-01 08:05:21

标签: c# string split serial-port

我有来自串行设备的十六进制数据流,格式如下:

F4 01 09 05 05 F4 01 09 05 05 F4 F 01 09 05 05 F4 01 09 05 05 

我需要做的(在C#中)读取传入的字符串,并将其拆分为“F4”的块,以进行处理。所以我得到了:

string DataToProcess = "F4 01 09 05 05";

每个部分都会更新。

我对解决这个问题的最佳方法感到有些困惑。

我有:

byte[] data = new byte[count];
 _serialPort.Read(data, 0, data.Length);

string rawString = BitConverter.ToString(data, 0);

if (rawString.Contains("F4"))
{
     //split here?                    
}

由于它是实时流,count变量总是在变化。我如何“等待”F4,并从一个部分创建子字符串?

谢谢。

3 个答案:

答案 0 :(得分:2)

我建议将data分组,而不将数组转换为字符串

byte[] data = new byte[] {
    0xF4, 0x01, 0x09, 0x05, 0x05, ..., 0x09, 0x05, 0x05 };

// Using side effect in not the best practice, but helpful
int group = 0;

var result = data
  .GroupBy(item => item == 0xF4 ? ++group : group)
  .Select(chunk => chunk.ToArray());
//.ToArray(); // <- if you want to materialize

测试

string report = string.Join(Environment.NewLine, result
  .Select(array => string.Join(", ", array
     .Select(item => item.ToString("X2")))));

Console.Write(report);

结果

F4, 01, 09, 05, 05
F4, 01, 09, 05, 05
F4, 0F, 01, 09, 05, 05
F4, 01, 09, 05, 05

答案 1 :(得分:1)

您可以使用string.Split(string[], StringSplitOptions)与LINQ混合来按每个F4进行拆分:

if (rawString.Contains("F4"))
{
    string[] dataToProcess = rawString.Split(new string[] { "F4" }, StringSplitOptions.None).Select(l => "F4" + l).ToArray();
}

答案 2 :(得分:1)

使用固定大小的缓冲区并在数据进入时解析数据。例如:

byte[] buffer = new byte[2048];
while (_serialPort.Read(data, 0, data.Length) > 0) {
    String rawString = Encoding.ASCII.GetString(buffer);
    String[] splitted = rawString.Split("\u00F4");
    // work with splitted
}

请注意,上面的示例使用ASCII解码而不是BitConverter.ToString。如果您需要使用字节,那么为什么首先将其转换为String?您也可以使用字节,C#支持0xF4之类的语法,它代表十六进制格式的数字。