Convert byte array to int - c#

I am trying to do some conversion in C#, and I am not sure how to do this:
private int byteArray2Int(byte[] bytes)
{
// bytes = new byte[] {0x01, 0x03, 0x04};
// how to convert this byte array to an int?
return BitConverter.ToInt32(bytes, 0); // is this correct?
// because if I have a bytes = new byte [] {0x32} => I got an exception
}
private string byteArray2String(byte[] bytes)
{
return System.Text.ASCIIEncoding.ASCII.GetString(bytes);
// but then I got a problem that if a byte is 0x00, it show 0x20
}
Could anyone give me some ideas?

BitConverter is the correct approach.
Your problem is because you only provided 8 bits when you promised 32. Try instead a valid 32-bit number in the array, such as new byte[] { 0x32, 0, 0, 0 }.
If you want an arbitrary length array converted, you can implement this yourself:
ulong ConvertLittleEndian(byte[] array)
{
int pos = 0;
ulong result = 0;
foreach (byte by in array) {
result |= ((ulong)by) << pos;
pos += 8;
}
return result;
}
It's not clear what the second part of your question (involving strings) is supposed to produce, but I guess you want hex digits? BitConverter can help with that too, as described in an earlier question.

byte[] bytes = { 0, 0, 0, 25 };
// If the system architecture is little-endian (that is, little end first),
// reverse the byte array.
if (BitConverter.IsLittleEndian)
Array.Reverse(bytes);
int i = BitConverter.ToInt32(bytes, 0);
Console.WriteLine("int: {0}", i);

this is correct, but you're
missing, that Convert.ToInt32
'wants' 32 bits (32/8 = 4 bytes)
of information to make a conversion,
so you cannot convert just One byte:
`new byte [] {0x32}
absolutely the the same trouble
you have. and do not forget about
the encoding you use: from encoding to encoding you have 'different byte count per symbol'

A fast and simple way of doing this is just to copy the bytes to an integer using Buffer.BlockCopy:
UInt32[] pos = new UInt32[1];
byte[] stack = ...
Buffer.BlockCopy(stack, 0, pos, 0, 4);
This has the added benefit of being able to parse numerous integers into an array just by manipulating offsets..

Related

C#: storing 16 bit data

I have written the following code in C# to get 16-bit twos compliment values over uart from 8 bit microcontroller. I am receiving data in bytes form. So I am combining the two bytes to form a 16-bit value. My issue is that my all values are becoming negative, but in reality some are negative some are not. Please tell me what is wrong of the following code that I am doing:
int t = 0;
int bytes = serialPort1.BytesToRead;
byte[] buffer = new byte[bytes];
serialPort1.Read(buffer, 0, bytes);
float [] buffer2 = new float[bytes];
for(int i=0;t< buffer.Length;i++)
{
buffer2[i]= ~(((buffer[t]<< 8) | buffer[t+1]) - 1);
t = t + 2;
}

Why I can't convert a byte[2] array to int with BitConverter?

The main problem is that I recive a binary number with only 10 bits in use from a SerialPort so I use this to receive the complete data:
byte[] buf = new byte[2];
serialPort.Read(buf, 0, buf.Length);
BitArray bits = new BitArray(buf);
The original idea for convert binary to int was this:
foreach (bool b in bits)
{
if(b){
binary += "1";
}
else{
binary+= "0";
}
}
decimal = Convert.ToInt32(binary, 2);
decimal = decimal >> 6;
binary is obviously a string, that works but I need to know if exists another solution, instead of the previuos code I try with this:
decimal = BitConverter.ToInt16(buf, 0);
But this only read the first 8 bits, I need the other 2 bits missing! If I change ToInt16 for a ToInt32
decimal = BitConverter.ToInt32(buf, 0);
The program stops for a System.ArgumentException: Destination array was not long enough...
What can I do?
You can just shift the values in the bytes so that they match, and put them together. If I got the use of bits right, that would be:
int value = (buf[0] << 2) | (buf[1] >> 6);

C# Reading, Storing, and Combining Arrays

I am working on an RS232 communication effort but have been running into issues with the some of the arrays I am handling.
In the example below I am sending out a "Command" with the intent to read and store the first 4 bytes of the command in a new array called "FirstFour". For every loop execution that is run I also want to convert the integer "i" to a Hex value. I then intend to combine the "FirstFour" and "iHex" arrays into a new array noted as "ComboByte". Below is my code so far but it doesn't seem to be working.
private void ReadStoreCreateByteArray()
{
byte[] Command = { 0x01, 0x02, 0x05, 0x04, 0x05, 0x06, 0x07, 0x08};
for (int i = 0; i < 10; i++)
{
//Send Command
comport.Write(Command, 0, Command.Length);
//Read response and store in buffer
int bytes = comport.BytesToRead;
byte[] Buffer = new byte[bytes];
comport.Read(Buffer, 0, bytes);
//Create 4 byte array to hold first 4 bytes out of Command
var FirstFour = Buffer.Take(4).ToArray();
//Convert i to a Hex value
byte iHex = Convert.ToByte(i.ToString());
//Combine "FirstFour" and "iHex" into a new array
byte [] ComboByte = {iHex, FirstFour[1], FirstFour[2], FirstFour[3], First Four[4]};
comport.Write(ComboByte, 0, ComboByte.Length);
}
}
Any help would be appreciated. Thanks!
Arrays are zero based, so...
byte [] ComboByte = {iHex, FirstFour[0], FirstFour[1], FirstFour[2], First Four[3]};
...should give you the first 4 elements of FirstFour.
Firstly, you need to handle the return value from Read operations. The following pattern should work fine for a range of APIs, including SerialPort, Stream, etc:
static void ReadExact(SerialPort port, byte[] buffer, int offset, int count)
{
int read;
while(count > 0 && (read = port.Read(buffer, offset, count)) > 0)
{
count -= read;
offset += read;
}
if (count != 0) throw new EndOfStreamException();
}
So: you have a method that can read a reliable number of bytes - you should then be able to re-use a single buffer and populate it sequentially:
byte[] buffer = new byte[5];
for (int i = 0; i < 10; i++)
{
//...
buffer[0] = (byte)i;
ReadExact(port, buffer, 1, 4);
}
The BytesToRead property is largely useless except for deciding whether to read synchronously or asynchronously, as it doesn't tell you whether more data is imminent. With your existing code there is no guarantee you will have at least 4 bytes.

Read or convert to Int32 from TWO byte arrays

I have the 4 bytes that represent an integer stored in 2 separate byte arrays. I would like to convert these into an Int32 WITHOUT copying to a third byte array and reading that using memorystream.
The reason the data is split across two byte arrays is because this is a simplified example of my issue which involves huge amounts of data that cannot fit into a single bytearray.
Is there any way to achieve this? I do not wish to concatenate the two byte arrays into a thrid because of the performance implications which are critical to me.
Moon
You can use a struct layout like this
[StructLayout(LayoutKind.Explicit, Size=4)]
struct UnionInt32Value
{
[FieldOffset(0)] public byte byte1;
[FieldOffset(1)] public byte byte2;
[FieldOffset(2)] public byte byte3;
[FieldOffset(3)] public byte byte4;
[FieldOffset(0)] public Int32 iVal;
}
Assign your bytes in the correct order then read your Int32 from iVal;
EDIT: Sample code
using System;
using System.Runtime.InteropServices;
namespace Test
{
class Program
{
[StructLayout(LayoutKind.Explicit, Size=4)]
struct UnionInt32Value
{
[FieldOffset(0)] public byte byte1;
[FieldOffset(1)] public byte byte2;
[FieldOffset(2)] public byte byte3;
[FieldOffset(3)] public byte byte4;
[FieldOffset(0)] public Int32 iVal;
}
public static void Main(string[] args)
{
UnionInt32Value v = new UnionInt32Value();
v.byte1=1;
v.byte2=0;
v.byte3=0;
v.byte4=0;
Console.WriteLine("this is one " + v.iVal);
v.byte1=0xff;
v.byte2=0xff;
v.byte3=0xff;
v.byte4=0xff;
Console.WriteLine("this is minus one " + v.iVal);
Console.Write("Press any key to continue . . . ");
Console.ReadKey(true);
}
}
}
Something like this?
int x = (array1[index] << 16) + array2[index];
Of course, you didn't specify a language, but that's the gist of it.
The BitConverter class is intended for this:
byte[] parts = { byte1, byte2, byte3, byte4 };
int value = BitConverter.ToInt32(parts, 0);
You can use BitConverter twice, like:
byte[] bytes0 = new byte[] { 255, 255 };
byte[] bytes1 = new byte[] { 0, 0 };
int res = BitConverter.ToInt16(bytes0, 0) << 16;
res |= BitConverter.ToUInt16(bytes1, 0);
Which yields -65536 (0b11111111 11111111 00000000 00000000)
If your integer parts isn't at position 0 in the array, you just replace the 0 in ToUint16 to change the position.
Little extension method:
public static class BitConverterExt
{
public static int ToInt32(byte[] arr0, int index0, byte[] arr1, int index1)
{
int partRes = BitConverter.ToInt16(arr1, index1) << 16;
return partRes | BitConverter.ToUInt16(arr0, index0);
}
}
Usage:
byte[] bytes0 = new byte[] { 0x0, 0xA };
byte[] bytes1 = new byte[] { 0x64, 0xFF };
int res = BitConverterExt.ToInt32(bytes0, 0, bytes1, 0);
//Res -10221056 (0xFF640A00)
If I understand correctly, you are having a problem whilst reading across the boundary of the two arrays. If that is so, this routine will read an integer anywhere in the two arrays, even if it is across the two of them.
int ReadInteger(byte[] array1, byte[] array2, int offset)
{
if (offset < 0 || (offset + 4) > (array1.Length + array2.Length))
throw new ArgumentOutOfRangeException();
if (offset <= (array1.Length - 4))
return BitConverter.ToInt32(array1, offset);
else if (offset >= array1.Length)
return BitConverter.ToInt32(array2, offset - array1.Length);
else
{
var buffer = new byte[4];
var numFirst = array1.Length - offset;
Array.Copy(array1, offset, buffer, 0, numFirst);
Array.Copy(array2, 0, buffer, numFirst, 4 - numFirst);
return BitConverter.ToInt32(buffer, 0);
}
}
Note: depending on how your integers are stored, you might want to change the order in which bytes are copied.

How to convert an int[,] to byte[] in C#

How to convert an int[,] to byte[] in C#?
Some code will be appreciated
EDIT:
I need a function to perform the following:
byte[] FuncName (int[,] Input)
Since there is very little detail in your question, I can only guess what you're trying to do... Assuming you want to "flatten" a 2D array of ints into a 1D array of bytes, you can do something like that :
byte[] Flatten(int[,] input)
{
return input.Cast<int>().Select(i => (byte)i).ToArray();
}
Note the call to Cast : that's because multidimensional arrays implement IEnumerable but not IEnumerable<T>
It seem that you are writing the types wrong, but here is what you might be looking for:
byte[] FuncName (int[,] input)
{
byte[] byteArray = new byte[input.Length];
int idx = 0;
foreach (int v in input) {
byteArray[idx++] = (byte)v;
}
return byteArray;
}
Here's an implementation that assumes you are attempting serialization; no idea if this is what you want, though; it prefixes the dimensions, then each cell using basic encoding:
public byte[] Encode(int[,] input)
{
int d0 = input.GetLength(0), d1 = input.GetLength(1);
byte[] raw = new byte[((d0 * d1) + 2) * 4];
Buffer.BlockCopy(BitConverter.GetBytes(d0), 0, raw, 0, 4);
Buffer.BlockCopy(BitConverter.GetBytes(d1), 0, raw, 4, 4);
int offset = 8;
for(int i0 = 0 ; i0 < d0 ; i0++)
for (int i1 = 0; i1 < d1; i1++)
{
Buffer.BlockCopy(BitConverter.GetBytes(input[i0,i1]), 0,
raw, offset, 4);
offset += 4;
}
return raw;
}
The BitConverter converts primitive types to byte arrays:
byte[] myByteArray = System.BitConverter.GetBytes(myInt);
You appear to want a 2 dimensional array of ints to be converted to bytes. Combine the BitConverter with the requisite loop construct (e.g foreach) and whatever logic you want to combine the array dimensions.

Categories