How to interpret byte as int? - c#

I have a byte array recived from Cpp program.
arr[0..3] // a real32,
arr[4] // a uint8,
How can I interpret arr[4] as int?
(uint)arr[4] // Err: can't implicitly convert string to int.
BitConverter.ToUint16(arr[4]) // Err: Invalid argument.
buff[0+4] as int // Err: must be reference or nullable type
Do I have to zero consecutive byte to interpret it as a UInt16?
OK, here is the confusion. Initially, I defined my class.
byte[] buff;
buff = getSerialBuffer();
public class Reading{
public string scale_id;
public string measure;
public int measure_revised;
public float wt;
}
rd = new Reading();
// !! here is the confusion... !!
// Err: Can't implicitly convert 'string' to 'int'
rd.measure = string.Format("{0}", buff[0 + 4]);
// then I thought, maybe I should convert buff[4] to int first ?
// I throw all forms of conversion here, non worked.
// but, later it turns out:
rd.measure_revised = buff[0+4]; // just ok.
So basically, I don't understand why this happens
rd.measure = string.Format("{0}", buff[0 + 4]);
//Err: Can't implicitly convert 'string' to 'int'
If buff[4] is a byte and byte is uint8, what does it mean by can't implicitly convert string to int ?... It confuses me.

You were almost there. Assuming you wanted a 32-bit int from the first 4 bytes (it's hard to interpret your question):
BitConverter.ToInt32(arr, 0);
This says to take the 4 bytes from arr, starting at index 0, and turn them into a 32-bit int. (docs)
Note that BitConverter uses the endianness of the computer, so on x86/x64 this will be little-endian.
If you want to use an explicit endianness, you'll need to construct the int by hand:
int littleEndian = arr[0] | (arr[1] << 8) | (arr[2] << 16) | (arr[3] << 24);
int bigEndian = arr[3] | (arr[2] << 8) | (arr[1] << 16) | (arr[0] << 24);
If instead you wanted a 32-bit floating-point number from the first 4 bytes, see Dmitry Bychenko's answer.

If I've understood you right you have byte (not string) array
byte[] arr = new byte[] {
182, 243, 157, 63, // Real32 - C# Single or float (e.g. 1.234f)
123 // uInt8 - C# byte (e.g. 123)
};
To get float and byte back you can try BitConverter
// read float / single starting from 0th byte
float realPart = BitConverter.ToSingle(arr, 0);
byte bytePart = arr[4];
Console.Write($"Real Part: {realPart}; Integer Part: {bytePart}");
Outcome:
Real Part: 1.234; Integer Part: 123
Same idea (BitConverter class) if we want to encode arr:
float realPart = 1.234f;
byte bytePart = 123;
byte[] arr =
BitConverter.GetBytes(realPart)
.Concat(new byte[] { bytePart })
.ToArray();
Console.Write(string.Join(" ", arr));
Outcome:
182 243 157 63 123

Related

Does C# have a way to write an object with int fields (byte, ushort, ulong, etc.) as a byte array?

I'm trying to convert an object with only int fields (ushort, ulong, uint, int, etc.) into a byte array containing each int as a byte in the order that it appears in the object.
For example, if I have an object of the form
obj = {subobj: {uint firstProp: 500, ushort secondProp: 12}, byte lastProp: 5}
then I expect the byte array to be
{0, 0, 1, 244, 0, 12, 5}
I tried to create this byte array by using Serialization (as described in this answer), but I'm noticing there's a bunch of stuff before and after each byte. Based on this website, I believe this represents the database and the file, which I don't want.
I know that in C++ I can use reinterpret_cast<uint8_t*>(obj) to get the desired result. Is there an equivalent way to do this in C#?
You can try do something like this:
foreach(int value in obj)
{
byte lsbOfLsb = (byte)value;
byte msbOfLsb = (byte)(value >> 8);
byte lsbOfMsb = (byte)(value >> 16);
byte msbOfMsb = (byte)(value >> 24);
}
Obviously this is only the idea.
You should use a for loop instead of a foreach and Parse all elements to int e.g. .
Other way is to check the type of data with
typeof(value) //op 1
// OR
if(value is int) //e.g.
and then convert to byte as you need.

How can I store 4 8 bit coordinates into one integer (C#)?

Lets say I have the following four variables: player1X, player1Y, player2X, player2Y. These have, for example, respectively the following values: 5, 10, 20, 12. Each of these values is 8 bits at max and I want to store them into one integer (32 bits), how can I achieve this?
By doing this, I want to create a dictionary, keeping count of how often certain states have happened in the game. For example, 5, 10, 20, 12 is one state, 6, 10, 20, 12 would be another.
You can use BitConverter
To get one Integer out of 4 bytes:
int i = BitConverter.ToInt32(new byte[] { player1X, player1Y, player2X, player2Y }, 0);
To get the four bytes out of the integer:
byte[] fourBytes = BitConverter.GetBytes(i);
To "squeeze" 4 8 bits value in a 32 bit space, you need to "shift" the bits for your various values, and add them together.
The opposite operations is to "unshift" and use some modulo to get the individual numbers you need.
Here is an alterantive:
Make a struct with defined packing. Expose:
The int32 and all 4 bytes at the same time
Make sure the apcking overlaps (i.e. int starts at 0, byte variables at 0, 1,2,3
Done.
And you can easily access and work with them WITHOUT a bitconverter et al and never have to define an array, which is expensive jsut to throw it away.
You can place the values by shifting to the apropriate offset
Example:
// Composing
byte x1 = ...;
byte x2 = ...;
byte x3 = ...;
byte x4 = ...;
uint x = x1 | (x2 << 0x8) | (x3 << 0x10) | (x4 << 0x18);
// Decomposing
uint x = ...;
byte x1 = x & 0xFF;
byte x2 = (x >> 0x8) & 0xFF;
byte x3 = (x >> 0x10) & 0xFF;
byte x4 = (x >> 0x18) & 0xFF;

What is the equivalent of this swift Uint8 conversion in c#?

i'm trying to convert this swift snippet in c#, but i'm a bit confused. Basically, i need this function to get the Ranging Data from beacons, as is indicated here: https://github.com/google/eddystone/tree/master/eddystone-uid
func getTxPower( frameData: NSData) -> Int
{
let count = frameData.length
var frameBytes = [UInt8](repeating: 0, count: count)
frameData.getBytes(&frameBytes, length: count)
let txPower = Int(Int8(bitPattern:frameBytes[1]))
return txPower
}
I get a NSData and i convert it into a UInt8 array. I just need to get the element in second position and convert it into a signed int.
This is the c# code i tried:
int getTxPower(NSData frameData)
{
var count = frameData.Length;
byte[] frameBytes = new byte[Convert.ToInt32(count)];
Marshal.Copy(frameData.Bytes, frameBytes,0,Convert.ToInt32(count));
int txPower = frameBytes[1];
return txPower;
}
I expected to get negative value too, because, as written in the link, the TxPower has a value range from -100 dBm to +20 dBm at a resolution of 1 dBm.
Thanks to those who will help me.
Presumably instead of:
int txPower = frameBytes[1];
(which just extends an unsigned byte to 32 bits)
int txPower = (int)((sbyte)frameBytes[1]);
(which reinterpets the unsigned byte as a signed byte, then extends to 32 bits)
Note that the (int) can be done implicitly, if it is clearer:
int txPower = (sbyte)frameBytes[1];

How can I store two smallint values in a varbinary(max)?

I am dealing with a SQL table that has a column of type varbinary(max). I intend to store two Int16 values in it via a stored procedure. I am going to consume this column value in C# code so I was hoping if I could do something like 'save one value in the first 8 bits and second value in last 8 bits', etc. I explored SQL bitwise operators but was unable to conclude how I can do it.
Would greatly appreciate if I can get any pointers or links to read-up.
You can convert the stored procedure parameters to binary and concatenate them:
DECLARE #T TABLE (BinaryValue VARBINARY(MAX))
DECLARE #Int1 SMALLINT
DECLARE #Int2 SMALLINT
SELECT
#Int1 = 32767,
#Int2 = -32768
INSERT #T (BinaryValue)
SELECT CAST(ISNULL(#Int1,0) AS VARBINARY(2)) + CAST(ISNULL(#Int2,0) AS VARBINARY(2))
SELECT
BinaryValue,
Int1 = CAST(SUBSTRING(BinaryValue, 1, 2) AS SMALLINT) ,
Int2 = CAST(SUBSTRING(BinaryValue, 3, 2) AS SMALLINT)
FROM
#T
To store 2 Int16 values, you obviously need a total of 32 bits, or 4 bytes. Here is some C# code that shows you how you can convert your 2 Int16 values to a byte array and back the other way around using bit shifting.
I realize that you may need to do some of this inside a stored procedure. But if you study the simple bit shifting logic, you shouldn't have a hard time translating the logic into your procedure.
Hopefully this will get you started:
public static void Main(string[] args)
{
Int16 value1 = 12345;
Int16 value2 = 31210;
byte[] bytes = new byte[4];
bytes[0] = (byte)(value1 >> 8);
bytes[1] = (byte)value1;
bytes[2] = (byte)(value2 >> 8);
bytes[3] = (byte)value2;
// store the byte array in your db column.
// Now let's pretend we're reading the byte array and converting back to our numbers.
Int16 decodedValue1 = (Int16)((bytes[0] << 8) | bytes[1]);
Int16 decodedValue2 = (Int16)((bytes[2] << 8) | bytes[3]);
Console.WriteLine(decodedValue1); // prints 12345
Console.WriteLine(decodedValue2); // prints 31210
}
Here is another way to do it without explicit bit shifting in C#, by using the built-in BitConverter class:
public static void Main(string[] args)
{
Int16 value1 = 12345;
Int16 value2 = 31210;
byte[] bytes = new byte[4];
Array.Copy(BitConverter.GetBytes(value1), 0, bytes, 0, 2);
Array.Copy(BitConverter.GetBytes(value2), 0, bytes, 2, 2);
// store the byte array in your db column.
// Now let's pretend we're reading the byte array and converting back to our numbers.
Int16 decodedValue1 = BitConverter.ToInt16(bytes, 0);
Int16 decodedValue2 = BitConverter.ToInt16(bytes, 2);
Console.WriteLine(decodedValue1); // prints 12345
Console.WriteLine(decodedValue2); // prints 31210
}

Is there a built in function to expand a byte[] leaving zeros at the beginning?

I've got this code
BitConverter.GetBytes(width).CopyTo(resultBytes, 0);
If the width is 12 it returns one byte not 4, is there a built in function to resize the array leaving 0's at the beginning
to output [0, 0, 0, 12] instead of [12].
What is the type of width? Bit converter just converts the type to an array of appropriate size. If you say
long x = 1 ;
int y = 2 ;
short z = 3 ;
byte[] x_bytes = BitConverter.GetBytes(x) ;
byte[] y_bytes = BitConverter.GetBytes(y) ;
byte[] z_bytes = BitConverter.GetBytes(z) ;
You'll get back 8-, 4- and 2-byte arrays, respectively. You can cast to the desired type:
byte[] bytes = BitConverter.GetBytes( (int) x ) ;
And if you say something like
byte[] bytes = BitConverter.GetBytes(1) ;
You'll get back an array of 4 bytes: the type of an unsuffixed integer literal is the smallest type in which will fit, in order of preference: int, uint, long, ulong. If the literal is suffixed, it will be the type specified by the suffix (e.g., 1L will give you an 8-byte long).
If you are converting an expression, such as:
byte[] bytes = BitConverter.GetBytes( ((3*x + 2&y + z) << 3 ) & 5L ) ;
What gets converted is, of course, the type produced by evaluating the expression.
you need to cast width to int in order to get 4 bytes, because the result of GetBytes() is dependent on the type passed in:
BitConverter.GetBytes((int)width).CopyTo(resultBytes, 0);
Maybe it's the simplest solution ever, but what about Array.Reverse:
BitConverter.GetBytes(4).CopyTo(resultBytes, 0); // [4, 0, 0, 0]
Array.Reverse(resultBytes); // [0, 0, 0, 4]

Categories

Resources