【问题标题】:C# How to extract multiple smaller byte[] from 1 bigger byte[]?C#如何从1个较大的字节[]中提取多个较小的字节[]?
【发布时间】:2015-02-18 12:06:54
【问题描述】:

这个问题与: C# How to extract bytes from byte array? With known starting byte

我有“100 bytes byte[]”,它由几个随机出现在较大字节中的“14 bytes 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

【问题讨论】:

  • 如何使用for 循环遍历原始数组?您应该如何处理生成的子数组?
  • 您只需将所有代码包装在一个循环中
  • 如果你的小数组只有 14 个元素,它怎么能在 16 个字节之后结束呢? 14、15 或 16 字节的倍数如何适合 100 字节?你的问题很难理解。哦,我错过了“随机”部分。您是否认为 0x55 总是开始一个 15 字节的序列,包括它本身?
  • “随机出现在更大的字节” 稍等。随机是什么意思?它们不是按顺序排列的吗?如果一个字节序列包含中间的值0x55怎么办?我假设它是 0x55 + 14 字节 + 校验和字节?
  • @PeterSchneider,是的,ox55 总是开始一个 16 字节的序列,包括它自己。忘记14,这是一个错误。 :)

标签: c# byte bytearray .net-micro-framework netduino


【解决方案1】:

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

(更新后编辑)

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

从索引i = 0 开始并在i + 15

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

您可以使用Array.IndexOf 跳到0x55 的第一次出现,但由于无论如何您都需要跟踪索引,您最好自己检查并简化代码(算法复杂度是相同的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# 新手(通常是编程),我建议您在方法中放置一个断点,并逐步了解发生了什么。

【讨论】:

  • 谢谢。在您的示例之前,我开始尝试实施它,并且找到了与您的解决方案接近的解决方案。但后来我看到你的,我对这一行很感兴趣: var receivedChecksum = (input[i + 2]
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-03-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多