3

ハードウェア デバイスとの間でデータを読み書きする C# WinForms アプリケーションに取り組んでいます。私のアプリケーションには、1 ~ 100000 の数字を含む複数選択リストボックスがあり、ユーザーは最大 10 個の数字を選択できます。各数値の選択が完了したら、ユーザーはボタンをクリックします。イベント ハンドラー コードは、選択した各数値を表すために 3 バイトを使用して固定サイズ (30 バイト) のバイト配列を作成し、数値が 10 未満の場合は配列をパディングする必要があります。選択されました。

例として、ユーザーが次の値を選択するとします。

17
99152
3064
52588
65536

現在、このコードを使用して各数値をバイト配列に変換しています。

byte[] bytes = BitConverter.GetBytes(selectedNumber);
Array.Reverse(bytes) // because BitConverter.IsLittleEndian() = true
Debug.WriteLine(BitConverter.ToString(bytes));

上記の数値については、次のようになります。

00-00-00-11
00-01-83-50
00-00-0B-F8
00-00-CD-6C
00-01-00-00

BitConverter は 4 バイト配列を返してくれますが、最後のバイト配列に各数値を格納するために 3 バイトを使用するスペースしかありません。個々のバイト配列の最上位バイトを削除して、次のように最終的な配列を作成できます。

00-00-11-01-83-50-00-0B-F8-00-CD-6C-01-00-00-[padding here]

それをデバイスに書き込むとうまくいくはずです。しかし、デバイスから配列 (または同様の配列) を読み取ると、少し問題が発生します。3 バイト配列があり、このコードを使用してそれを int に変換しようとすると...

int i = BitConverter.ToInt32(bytes, 0);

...「コレクション内のすべてのアイテムをコピーするには、Destination 配列の長さが足りません。」というメッセージが表示されます。3 バイトごとの先頭に 0x00 の最上位バイトを挿入し、それを変換できると思いますが、これを行うより良い方法はありますか?

4

2 に答える 2

8

ビットシフトを想像すると、|オペレーターがこれを行う最も効率的な方法になるはずです。

int i = (bytes[2] << 0) | (bytes[1] << 8) | (bytes[0] << 16);

また、注意として、最下位バイトではなく上位バイトを削除しています;p

于 2012-12-27T21:26:04.313 に答える
1
byte[] bytes = new byte[] { 0x00, 0x00, 0x11, 0x01, 0x83, 0x50, 0x00, 0x0B, 0xF8 };

var ints = bytes.Select((b, i) => new { b, i })
                .GroupBy(x => x.i / 3)
                .Select(g => BitConverter.ToInt32(
                                new byte[] { 0 }.Concat(g.Select(x => x.b))
                                                .Reverse()
                                                .ToArray(),
                                0))
                .ToArray();

or classically

var ints = new List<int>();
for (int i = 0; i < bytes.Length; i+=3)
{
    int intI=0;
    for (int j = i; j < i + 3; j++)
    {
        intI = intI * 256 + bytes[j]; //or (intI << 8) + bytes[j];
    }
    ints.Add(intI);
}

ints will be 17, 99152 and 3064

于 2012-12-27T21:33:32.120 に答える