【问题标题】:Best method to parse byte array with required chars only c#仅使用所需字符解析字节数组的最佳方法c#
【发布时间】:2020-01-08 10:09:08
【问题描述】:

我正在尝试从串口读取消息。我将其作为数据字节读取。我有一个字节数组,其中包含我从串口读取的所有数据字节。 我的字节数组在转换成字符串后保存了这样一个消息字符串。

\u0006\u0001\0d\o?\"\0$?##STA\r\nSystemLevel:Run\r\nstatus:1\r\nSensor Value:12.45\r\n...... ..........\r\n停止##

一旦匹配将所有内容转换为从索引点到某个索引长度的字符字符串,我就会从字节数组中查找某些字节模式(例如起始字节)。因为我知道我想要转换的消息的长度。 例如字节[25] 到字节[185]。

我只想知道从消息字符串中读取结果值的最佳方法是什么?结果值,例如 byte[28] 到 byte[32]、byte[42] 到 byte[49]...等。

将所有需要的字节转换为字符串并解析它会更好吗?还是使用几个字节模式来获取字符更好。这是最好的方法。

【问题讨论】:

  • 也许你需要 LINQ?
  • 先转换成字符串再解析字符串。这将有助于避免字符编码问题。否则,您可能会遇到编码为多个字节的字符(使用 UTF8 或其他)的问题。
  • @MatthewWatson 好的,谢谢您的建议。

标签: c# arrays string


【解决方案1】:

这是我在一个项目中使用的代码示例,其中 receiveMessage 是 byte[]

year = receiveMessage[4];
month = receiveMessage[5];
day = receiveMessage[6];
hour = receiveMessage[7];
minute = receiveMessage[8];
second = receiveMessage[9];
date = new DateTime(2000 + year, month, day, hour, minute, second);

WriteDBMessageLocation locationMessage = new WriteDBMessageLocation();
locationMessage.message = DATABASE_MESSAGE_TYPE.LOCATION;

locationMessage.trackTime = date;
locationMessage.currTime = DateTime.Now;

locationMessage.lattitude = new byte[4];
Array.Copy(receiveMessage, 11, locationMessage.lattitude, 0, 4);

locationMessage.longitude = new byte[4];
Array.Copy(receiveMessage, 15, locationMessage.longitude, 0, 4);
locationMessage.speed = receiveMessage[19];

locationMessage.courseStatus = new byte[2];
Array.Copy(receiveMessage, 20, locationMessage.courseStatus, 0, 2);

locationMessage.IMEI = byteState.Value.IMEI;
WriteDBAsync.ReadWriteFifo(WriteDBAsync.Mode.WRITE, locationMessage);```


【讨论】:

  • 最好只复制某些字节并将其转换为文本。谢谢。
【解决方案2】:

你总是可以用 for 循环做一些事情,像这样:

using System;
using System.Text;

namespace _ {
  class Q {
    public static void Main(string[] args) {
      string str = @"\u0006\u0001\0d\o?\""\0$?##STA\r\nSystemLevel:Run\r\nstatus:1\r\nSensor Value:12.45\r\n................\r\nSTOP##";
      byte[] bts = Encoding.UTF8.GetBytes(str);
      var g23to40 = getRange(bts, 22, 39);
      Console.WriteLine(Encoding.UTF8.GetString(g23to40));
    }
    public static byte[] getRange(byte[] a, int s, int e = -1) {
      if (e == -1) { e = a.Length-1; }
      if (e <= s) { return new byte[]{}; }
      byte[] r = new byte[e-s];
      int bi = 0;
      for (int i = s; i != e; i++) {
        if (i >= s && i <= e) {
          r[bi] = a[i];
          bi++;
        }
      }
      return r;
    }
  }
}

【讨论】:

    【解决方案3】:

    在我看来:

    1. 我会将其作为字节数组处理并删除标头/校验和内容/...

    byte.Skip(..).Take(...)

    1. 将该字节数组提供给一个函数,该函数将转换为正确的字符串格式,并进行处理。

    如果您在字节数组中搜索内容: 我猜你没有处理太多数据(100Mb+)。因为 Linq 不是最快的。

    Byte<Span>
    

    是更快的一个(.net Core)

    最快的在这里找到:

    byte[] array pattern search

    (Buffer.BlockCopy 的事情)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-11-15
      • 1970-01-01
      • 2011-03-13
      • 2012-04-24
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多