C#如何从1个较大的字节[]中提取多个较小的字节[]?

时间:2015-02-18 12:06:54

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

  

这个问题与以下内容有关:   C# How to extract bytes from byte array? With known starting byte

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

1 个答案:

答案 0 :(得分: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的段。
    • 要么收益率返回此结果,要么立即处理。
  5. 将i增加16以跳过已处理的块并重新开始。
  6. 您可以使用0x55跳转到第一次出现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#(通常是编程),我建议您在方法中放置一个断点,然后一步一步地了解发生了什么。