How to split byte array and assign to a byte variable? - c#

In my C# Application, I have a byte array as follows.
byte[] byteArray = {0x2, 0x2, 0x6, 0x6};
I need to split the first two elements i.e 0x2 and 0x2 and assign it to a byte variable. Similarly last two elements should be assigned to another byte variable.
i.e
byte FirstByte = 0x22;
byte SecondByte = 0x66;
I can split the array into sub arrays but I am not able find a way to convert byteArray into a single byte.

You can just bitwise OR them together, shifting one of the nibbles using <<:
byte firstByte = (byte)(byteArray[0] | byteArray[1] << 4);
byte secondByte = (byte)(byteArray[2] | byteArray[3] << 4);
You didn't specify the order in which to combine the nibbles, so you might want this:
byte firstByte = (byte)(byteArray[1] | byteArray[0] << 4);
byte secondByte = (byte)(byteArray[3] | byteArray[2] << 4);

Related

How to bit-shift and concatenate to get correct result?

I'm currently struggling with modbus tcp and ran into a problem with interpreting the response of a module. The response contains two values that are encoded in the bits of an array of three UInt16 values, where the first 8 bits of r[0] have to be ignored.
Let's say the UInt16 array is called r and the "final" values I want to get are val1 and val2, then I would have to do the following:
In the above example the desired output values are val1 (=3) and val2 (=6) for the input values r[0]=768, r[1]=1536 and r[2]=0, all values as UInt16.
I already tried to (logically) bit-rightshift r[0] by 8, but then the upper bits get lost because they are stored in the first 8 bits of r[1]. Do I have to concatenate all r-values first and bit-shift after that? How can I do that? Thanks in advance!
I already tried to (logically) bit-rightshift r[0] by 8, but then the upper bits get lost because they are stored in the first 8 bits of r[1].
Well they're not "lost" - they're just in r[1].
It may be simplest to break it down step by step:
byte val1LowBits = (byte) (r[0] >> 8);
byte val1HighBits = (byte) (r[1] & 0xff);
byte val2LowBits = (byte) (r[1] >> 8);
byte val2HighBits = (byte) (r[2] & 0xff);
uint val1 = (uint) ((val1HighBits << 8) | val1LowBits);
uint val2 = (uint) ((val2HighBits << 8) | val2LowBits);

Conversion of byte array hex to decimal

I have a byte array with hexadecimal values, for example:
var b = new byte[] {0x27, 0x01, 0x00, 0x00};
I need to convert this to decimal value, but when I used code below, get unexpected result. Expected is 295, but result is 654376960.
if (BitConverter.IsLittleEndian) Array.Reverse(b);
//int myInt = b[0] | (b[1] << 8) | (b[2] << 16) | (b[3] << 24);
int value = BitConverter.ToInt32(b, 0);
What's wrong?
Basically your understanding of endianness is wrong - your example is in little-endian format already, so you should only reverse it if BitConverter expects a big-endian format. You just need to invert your condition:
if (!BitConverter.IsLittleEndian) Array.Reverse(b);
(I'd personally put the body of the if statement in braces and new lines, but that's a different matter.)

Removing bits from first byte and then rejoining the bits

I have a devious little problem to which I think I've come up with a solution far more difficult than needs to be.
The problem is that I have two bytes. The first two bits of the first byte are to be removed (as the value is little endian, these bits are effectively in the middle of the 16 bit value). Then the least significant two bits of the second byte are to be moved to the most significant bit locations of the first byte, in place of the removed bits.
My solution is as follows:
byte firstByte = (byte)stream.ReadByte(); // 01000100
byte secondByte = (byte)stream.ReadByte(); // 00010010
// the first and second byte equal the decimal 4676 in this little endian example
byte remainderOfFirstByte = (byte)(firstByte & 63); // 01000100 & 00111111 = 00000100
byte transferredBits = (byte)(secondByte << 6); // 00010010 << 6 = 10000000
byte remainderOfSecondByte = (byte)(secondByte >> 2); // 00010010 >> 2 = 00000100
byte newFirstByte = (byte)(transferredBits | remainderOfFirstByte); // 10000000 | 00000100 = 10000100
int result = BitConverter.ToInt32(new byte[]{newFirstByte, remainderOfSecondByte, 0, 0}, 0); //10000100 00010000 (the result is decimal 1156)
Is there an easier way* to achieve this?
*less verbose, perhaps an inbuilt function or trick I'm missing? (with the exception of doing both the & and << on the same line)
You don't have to mask out bits that a shift would throw away anyway. And you don't have to transfer those bits manually. So it becomes this: (not tested)
int result = (secondByte << 6) | (firstByte & 0x3F);

Convert 16-bit signed int to 2-bytes?

I got an array which contains signed int data, i need to convert each value in the array to 2 bytes. I am using C# and i tried using BitConverter.GetBytes(int) but it returns a 4 byte array.
A signed 16-bit value is best represented as a short rather than int - so use BitConverter.GetBytes(short).
However, as an alternative:
byte lowByte = (byte) (value & 0xff);
byte highByte = (byte) ((value >> 8) & 0xff);

Convert byte array to short array in C#

I'm currently reading a file and wanted to be able to convert the array of bytes obtained from the file into a short array.
How would I go about doing this?
Use Buffer.BlockCopy.
Create the short array at half the size of the byte array, and copy the byte data in:
short[] sdata = new short[(int)Math.Ceiling(data.Length / 2)];
Buffer.BlockCopy(data, 0, sdata, 0, data.Length);
It is the fastest method by far.
One possibility is using Enumerable.Select:
byte[] bytes;
var shorts = bytes.Select(b => (short)b).ToArray();
Another is to use Array.ConvertAll:
byte[] bytes;
var shorts = Array.ConvertAll(bytes, b => (short)b);
A shorthard is a compound of two bytes. If you are writing all the shorts to the file as true shorts then those conversions are wrong. You must use two bytes to get the true short value, using something like:
short s = (short)(bytes[0] | (bytes[1] << 8))
short value = BitConverter.ToInt16(bytes, index);
I dont know, but I would have expected another aproach to this question.
When converting a sequence of bytes into a sequence of shorts, i would have it done like #Peter did
short s = (short)(bytes[0] | (bytes[1] << 8))
or
short s = (short)((bytes[0] << 8) | bytes[1])
depending on endianess of the bytes in the file.
But the OP didnt mention his usage of the shorts or the definition of the shorts in the file.
In his case it would make no sense to convert the byte array to a short array, because it would take twice as much memory, and i doubt if a byte would be needed to be converted to a short when used elsewhere.
short[] wordArray = Array.ConvertAll(byteArray, (b) => (short)b);
byte[] bytes;
var shorts = bytes.Select(n => System.Convert.ToInt16(n)).ToArray();

Categories