C# 如何从 1 个较大的 byte[] 中提取多个较小的 byte[]?
C# How to extract multiple smaller byte[] from 1 bigger byte[]?
This question is related to:
我有“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
我假设您的消息由一个起始 cookie 字节 0x55
、14 个字节的实际数据和 1 个校验和字节组成(因为您交替使用了 14 字节和 16 字节)。使随机出现的子数组有意义的唯一方法是在末尾有一个校验和值,以确认您的起始字节实际上是一个有效的 cookie(而不是数据字节)。
(更新后编辑)
因此,您的实际数据是 0x55 + 1syncbyte + 2 checksum + 12 databytes
,这意味着您的函数应该:
从索引 i
= 0 开始并在 i + 15
< 输入长度时重复:
- 检查索引
i
处的 cookie。
- 如果 cookie 不是 0x55,递增
i
并重新开始。
- 检查索引
i + 1
处的字节。
- 如果同步字节不正确,递增
i
并重新开始。
- 读取
i + 2
/[=22=处的16位校验和,计算实际数据校验和并进行比较。
- 如果校验和不匹配,递增
i
并重新开始。
- 将字节
i + 4
到 i + 15
复制到大小为 12 的段中。
- 要么产生 return 这个结果,要么立即处理它。
- 将 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# 新手(而且一般是编程新手),我建议您在方法内放置一个断点,然后逐步了解发生了什么。
This question is related to:
我有“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
我假设您的消息由一个起始 cookie 字节 0x55
、14 个字节的实际数据和 1 个校验和字节组成(因为您交替使用了 14 字节和 16 字节)。使随机出现的子数组有意义的唯一方法是在末尾有一个校验和值,以确认您的起始字节实际上是一个有效的 cookie(而不是数据字节)。
(更新后编辑)
因此,您的实际数据是 0x55 + 1syncbyte + 2 checksum + 12 databytes
,这意味着您的函数应该:
从索引 i
= 0 开始并在 i + 15
< 输入长度时重复:
- 检查索引
i
处的 cookie。- 如果 cookie 不是 0x55,递增
i
并重新开始。
- 如果 cookie 不是 0x55,递增
- 检查索引
i + 1
处的字节。- 如果同步字节不正确,递增
i
并重新开始。
- 如果同步字节不正确,递增
- 读取
i + 2
/[=22=处的16位校验和,计算实际数据校验和并进行比较。- 如果校验和不匹配,递增
i
并重新开始。
- 如果校验和不匹配,递增
- 将字节
i + 4
到i + 15
复制到大小为 12 的段中。- 要么产生 return 这个结果,要么立即处理它。
- 将 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# 新手(而且一般是编程新手),我建议您在方法内放置一个断点,然后逐步了解发生了什么。