-2

这个问题与: C#如何从字节数组中提取字节?已知起始字节

我有“100 bytes byte[]”,它由几个随机出现在较大字节中的“14 bytes byte[]”组成。

我较小的 byte[] 以 (byte) 0x55 开始并在 16 字节后结束

我正在使用代码:

        byte[] results = new byte[16];
        int index = Array.IndexOf(readBuffer, (byte)0x55, 2);
        Array.Copy(readBuffer, index, results, 0, 16);

但是有了这个,我只得到了我的较小字节[]的第一次出现。

如何获得所有较小的 byte[] 块?

PS:我正在使用 .Net Micro Framework

4

1 回答 1

1

我假设您的消息由一个起始 cookie 字节0x55、14 个实际数据字节和 1 个校验和字节组成(因为您交替使用 14 和 16 个字节)。使随机出现的子数组有意义的唯一方法是在末尾有一个校验和值,以确认您的起始字节实际上是一个有效的 cookie(而不是数据字节)。

(更新后编辑)

因此,您的实际数据是0x55 + 1syncbyte + 2 checksum + 12 databytes,这意味着您的函数应该:

从 index = 0 开始并在< 输入长度i时重复:i + 15

  1. 检查 index 处的 cookie i
    • 如果 cookie 不是 0x55,则递增i并重新开始。
  2. 检查 index 处的字节i + 1
    • 如果同步字节不正确,则递增i并重新开始。
  3. i + 2在/处读取 16 位校验和i + 3,计算实际数据校验和并进行比较。
    • 如果校验和不匹配,则递增i并重新开始。
  4. 将字节复制i + 4i + 15大小为 12 的段中。
    • 要么 yield 返回这个结果,要么立即处理它。
  5. 将 i 增加 16 以跳过已处理的块并重新开始。

您可以跳到第一次出现0x55using Array.IndexOf,但由于无论如何您都需要跟踪索引,您不妨自己检查并简化代码(算法复杂度相同O(n))。

对此进行编码的一种方法是:

private static IEnumerable<byte[]> EnumerateSegments(byte[] input)
{
    var i = 0;
    while (i + 15 < input.Length)
    {
        // check if it starts with 'sync' bytes
        // (not sure which is the second one, though?)
        var cookie = input[i];
        if (input[i] != 0x55 || input[i + 1] != 0xAA)
        {
            i++;
            continue;
        }

        // get the 16-bit checksum
        // (check if this is the correct endian, i.e. you
        // might need to swap bytes)
        var receivedChecksum = (input[i + 2] << 8) | (input[i + 3]);

        // calculate the checksum over data only
        var calculatedChecksum = CalculateChecksum(input, i + 4, 12);
        if (receivedChecksum != calculatedChecksum)
        {
            i++;
            continue;
        }

        // if we're here, data should be valid, so the last
        // thing left to do is to copy the data into the subarray
        var segment = new byte[12];
        Array.Copy(input, i + 4, segment, 0, 12);
        yield return segment;

        // skip this segment
        i += 16;
    }
}

您将在foreach循环中使用它来迭代段:

foreach (var segment in EnumerateSegments(input)) 
{
    ProcessSegment(segment);
}

或者,如果您想多次遍历元素,您可以获得一个段列表:

List<byte[]> listOfSegments = EnumerateSegments(input).ToList();

由于您是 C# 新手(通常是编程),我建议您在方法中放置一个断点,并逐步了解发生了什么。

于 2015-02-18T12:33:30.653 回答