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 0x5514 байтов фактических данных и 1 байт контрольной суммы (поскольку вы использовали взаимозаменяемо 14 и 16 байтов). Единственный способ иметь смысл в случайно встречающихся подмассивах - это иметь значение контрольной суммы в конце, чтобы подтвердить, что ваш начальный байт является действительным файлом cookie (а не байтом данных).

(отредактировано после вашего обновления)

Итак, ваши фактические данные 0x55 + 1syncbyte + 2 checksum + 12 databytesЭто означает, что ваша функция должна:

Начните с индекса i = 0 и повторите, пока i + 15 <длина ввода:

  1. Проверьте куки в индексе i,
    • Если cookie не 0x55, увеличить i и начни снова.
  2. Проверьте байт по индексу i + 1,
    • Если неправильный байт синхронизации, увеличивается i и начни снова.
  3. Прочитайте 16-битную контрольную сумму на i + 2/i + 3, рассчитать фактическую контрольную сумму данных и сравнить.
    • Если контрольная сумма не совпадает, увеличить i и начни снова.
  4. Копировать байты i + 4 в i + 15 в сегмент размером 12.
    • Либо yield вернет этот результат, либо обработает его сразу.
  5. Увеличьте 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# (и вообще программировании), я предлагаю вам поместить точку останова в метод и идти шаг за шагом, чтобы понять, что происходит.

Другие вопросы по тегам