-2

この質問は関連しています: 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 を使用しています

4

1 に答える 1

1

あなたのメッセージは、開始 Cookie バイト0x55、14 バイトの実際のデータ、および 1 つのチェックサム バイトで構成されていると推測しています (14 バイトと 16 バイトを同じ意味で使用しているため)。ランダムに発生するサブ配列を意味のあるものにする唯一の方法は、最後にチェックサム値を付けて、開始バイトが実際に有効な Cookie (データ バイトではなく) であることを確認することです。

(更新後に編集されました)

したがって、実際のデータは です0x55 + 1syncbyte + 2 checksum + 12 databytes。つまり、関数は次のようにする必要があります。

インデックス = 0 で開始し、 < 入力長iの間繰り返す:i + 15

  1. index の Cookie を確認しますi
    • cookie が 0x55 でない場合は、インクリメントiしてやり直します。
  2. index のバイトを確認しますi + 1
    • 同期バイトが正しくない場合は、インクリメントiしてやり直します。
  3. i + 2/で 16 ビットのチェックサムを読み取り、i + 3実際のデータのチェックサムを計算して比較します。
    • チェックサムが一致しない場合は、インクリメントiしてやり直します。
  4. サイズ 12 のセグメントに バイトi + 4をコピーします。i + 15
    • yield がこの結果を返すか、すぐに処理します。
  5. i を 16 増やして、処理されたブロックをスキップし、最初からやり直します。

0x55usingの最初の出現までスキップできますが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# (および一般的なプログラミング) に不慣れなので、メソッド内にブレークポイントを配置し、何が起こっているのかを理解するために段階的に進むことをお勧めします。

于 2015-02-18T12:33:30.653 に答える