あなたのメッセージは、開始 Cookie バイト0x55
、14 バイトの実際のデータ、および 1 つのチェックサム バイトで構成されていると推測しています (14 バイトと 16 バイトを同じ意味で使用しているため)。ランダムに発生するサブ配列を意味のあるものにする唯一の方法は、最後にチェックサム値を付けて、開始バイトが実際に有効な Cookie (データ バイトではなく) であることを確認することです。
(更新後に編集されました)
したがって、実際のデータは です0x55 + 1syncbyte + 2 checksum + 12 databytes
。つまり、関数は次のようにする必要があります。
インデックス = 0 で開始し、 < 入力長i
の間繰り返す:i + 15
- index の Cookie を確認します
i
。
- cookie が 0x55 でない場合は、インクリメント
i
してやり直します。
- index のバイトを確認します
i + 1
。
- 同期バイトが正しくない場合は、インクリメント
i
してやり直します。
i + 2
/で 16 ビットのチェックサムを読み取り、i + 3
実際のデータのチェックサムを計算して比較します。
- チェックサムが一致しない場合は、インクリメント
i
してやり直します。
- サイズ 12 のセグメントに
バイト
i + 4
をコピーします。i + 15
- yield がこの結果を返すか、すぐに処理します。
- i を 16 増やして、処理されたブロックをスキップし、最初からやり直します。
0x55
usingの最初の出現までスキップできますがArray.IndexOf
、とにかくインデックスを追跡する必要があるため、自分でチェックしてコードを簡素化することもできます (アルゴリズムの複雑さは同じO(n)
です)。
これをコーディングする 1 つの方法は次のようになります。
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# (および一般的なプログラミング) に不慣れなので、メソッド内にブレークポイントを配置し、何が起こっているのかを理解するために段階的に進むことをお勧めします。