Question

I am working on a C# WinForms application that reads/writes data to/from a hardware device. My application has a multiselect listbox which contains the numbers 1 - 100000 and the user may select up to 10 numbers. When they're done selecting each number, the user clicks a button and my event handler code needs to build a fixed-size (30 bytes) byte array using 3 bytes to represent each selected number and pad the array if less than 10 numbers were selected.

As an example, suppose my user chooses the following values:

17
99152
3064
52588
65536

I'm currently using this code to convert each number into a byte array:

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

For the numbers I listed above, this produces the following:

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

BitConverter is giving me back a 4 byte array where I only have space to use 3 bytes to store each number in the final byte array. I can drop the most significant byte of each individual byte array and then build my final array like this:

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

Writing that to the device should work. But reading the array (or a similar array) back from the device causes a bit of a problem for me. When I have a 3 byte array and try to convert that into an int using this code...

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

...I get "Destination array is not long enough to copy all the items in the collection." I suppose I could insert a most significant byte of 0x00 at the beginning of every three bytes and then convert that but is there a better way to do this?

Was it helpful?

Solution

I would imagine bit shifting and the | operator should be the most efficient way of doing this.

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

Also, as a heads up, you're dropping the most significant byte, not the least significant byte ;p

OTHER TIPS

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

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top