C# Как извлечь несколько меньших байтов [] из 1 большего байта []?
Этот вопрос относится к: C# Как извлечь байты из байтового массива? С известным начальным байтом
У меня есть "100 байтов байта []", который состоит из нескольких "14 байтов байта []", которые случайно появляются в старшем байте.
Мой меньший байт [] начинается с (байта) 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 ответ
Я предполагаю, что ваше сообщение состоит из начального байта cookie 0x55
14 байтов фактических данных и 1 байт контрольной суммы (поскольку вы использовали взаимозаменяемо 14 и 16 байтов). Единственный способ иметь смысл в случайно встречающихся подмассивах - это иметь значение контрольной суммы в конце, чтобы подтвердить, что ваш начальный байт является действительным файлом cookie (а не байтом данных).
(отредактировано после вашего обновления)
Итак, ваши фактические данные 0x55 + 1syncbyte + 2 checksum + 12 databytes
Это означает, что ваша функция должна:
Начните с индекса i
= 0 и повторите, пока i + 15
<длина ввода:
- Проверьте куки в индексе
i
,- Если cookie не 0x55, увеличить
i
и начни снова.
- Если cookie не 0x55, увеличить
- Проверьте байт по индексу
i + 1
,- Если неправильный байт синхронизации, увеличивается
i
и начни снова.
- Если неправильный байт синхронизации, увеличивается
- Прочитайте 16-битную контрольную сумму на
i + 2
/i + 3
, рассчитать фактическую контрольную сумму данных и сравнить.- Если контрольная сумма не совпадает, увеличить
i
и начни снова.
- Если контрольная сумма не совпадает, увеличить
- Копировать байты
i + 4
вi + 15
в сегмент размером 12.- Либо yield вернет этот результат, либо обработает его сразу.
- Увеличьте i на 16, чтобы пропустить обработанный блок и начать заново.
Вы можете перейти к первому появлению 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# (и вообще программировании), я предлагаю вам поместить точку останова в метод и идти шаг за шагом, чтобы понять, что происходит.