How to convert an int to a little endian byte array? - c#

I have this function in C# to convert a little endian byte array to an integer number:
int LE2INT(byte[] data)
{
return (data[3] << 24) | (data[2] << 16) | (data[1] << 8) | data[0];
}
Now I want to convert it back to little endian..
Something like
byte[] INT2LE(int data)
{
// ...
}
Any idea?
Thanks.

The BitConverter class can be used for this, and of course, it can also be used on both little and big endian systems.
Of course, you'll have to keep track of the endianness of your data. For communications for instance, this would be defined in your protocol.
You can then use the BitConverter class to convert a data type into a byte array and vice versa, and then use the IsLittleEndian flag to see if you need to convert it on your system or not.
The IsLittleEndian flag will tell you the endianness of the system, so you can use it as follows:
This is from the MSDN page on the BitConverter class.
int value = 12345678; //your value
//Your value in bytes... in your system's endianness (let's say: little endian)
byte[] bytes = BitConverter.GetBytes(value);
//Then, if we need big endian for our protocol for instance,
//Just check if you need to convert it or not:
if (BitConverter.IsLittleEndian)
Array.Reverse(bytes); //reverse it so we get big endian.
You can find the full article here.
Hope this helps anyone coming here :)

Just reverse it, Note that this this code (like the other) works only on a little Endian machine. (edit - that was wrong, since this code returns LE by definition)
byte[] INT2LE(int data)
{
byte[] b = new byte[4];
b[0] = (byte)data;
b[1] = (byte)(((uint)data >> 8) & 0xFF);
b[2] = (byte)(((uint)data >> 16) & 0xFF);
b[3] = (byte)(((uint)data >> 24) & 0xFF);
return b;
}

Just do it in reverse:
result[3]= (data >> 24) & 0xff;
result[2]= (data >> 16) & 0xff;
result[1]= (data >> 8) & 0xff;
result[0]= data & 0xff;

Could you use the BitConverter class? It will only work on little-endian hardware I believe, but it should handle most of the heavy lifting for you.
The following is a contrived example that illustrates the use of the class:
if (BitConverter.IsLittleEndian)
{
int someInteger = 100;
byte[] bytes = BitConverter.GetBytes(someInteger);
int convertedFromBytes = BitConverter.ToInt32(bytes, 0);
}

BitConverter.GetBytes(1000).Reverse<byte>().ToArray();

Depending on what you're actually doing, you could rely on letting the framework handle the details of endianness for you by using IPAddress.HostToNetworkOrder and the corresponding reverse function. Then just use the BitConverter class to go to and from byte arrays.

Try using BinaryPrimitives in System.Buffers.Binary, it has helper methods for reading and writing all .net primitives in both little and big endian form.
byte[] IntToLittleEndian(int data)
{
var output = new byte[sizeof(int)];
BinaryPrimitives.WriteInt32LittleEndian(output, data);
return output;
}
int LittleEndianToInt(byte[] data)
{
return BinaryPrimitives.ReadInt32LittleEndian(data);
}

public static string decimalToHexLittleEndian(int _iValue, int _iBytes)
{
string sBigEndian = String.Format("{0:x" + (2 * _iBytes).ToString() + "}", _iValue);
string sLittleEndian = "";
for (int i = _iBytes - 1; i >= 0; i--)
{
sLittleEndian += sBigEndian.Substring(i * 2, 2);
}
return sLittleEndian;
}

You can use this if you don't want to use new heap allocations:
public static void Int32ToFourBytes(Int32 number, out byte b0, out byte b1, out byte b2, out byte b3)
{
b3 = (byte)number;
b2 = (byte)(((uint)number >> 8) & 0xFF);
b1 = (byte)(((uint)number >> 16) & 0xFF);
b0 = (byte)(((uint)number >> 24) & 0xFF);
}

Related

Byte formatting

Hello I'am new to using bytes in C#.
Say if I want to compare bytes based on the forms 0xxxxxxx and 1xxxxxxx. How would I get that first value for my comparison and at the same time remove it from the front?
Any help will be greatly appreciated.
Not sure I understand, but in C#, to write the binaray number 1000'0000, you must use hex notation. So to check if the left-most (most significant) bits of two bytes match, you can do e.g.
byte a = ...;
byte b = ...;
if ((a & 0x80) == (b & 0x80))
{
// match
}
else
{
// opposite
}
This uses bit-wise AND. To clear the most significant bit, you may use:
byte aModified = (byte)(a & 0x7f);
or if you want to assign back to a again:
a &= 0x7f;
You need to use binary operations like
a&10000
a<<1
This will check two bytes and compare each bit. If the bit is the same, it will clear that bit.
static void Main(string[] args)
{
byte byte1 = 255;
byte byte2 = 255;
for (var i = 0; i <= 7; i++)
{
if ((byte1 & (1 << i)) == (byte2 & (1 << i)))
{
// position i in byte1 is the same as position i in byte2
// clear bit that is the same in both numbers
ClearBit(ref byte1, i);
ClearBit(ref byte2, i);
}
else
{
// if not the same.. do something here
}
Console.WriteLine(Convert.ToString(byte1, 2).PadLeft(8, '0'));
}
Console.ReadKey();
}
private static void ClearBit(ref byte value, int position)
{
value = (byte)(value & ~(1 << position));
}
}

Convert int to little-endian formated bytes in C++ for blobId in Azure

Working with a base64 encoding for Azure (http://msdn.microsoft.com/en-us/library/dd135726.aspx) and I dont seem to work out how to get the required string back. I'm able to do this in C# where I do the following.
int blockId = 5000;
var blockIdBytes = BitConverter.GetBytes(blockId);
Console.WriteLine(blockIdBytes);
string blockIdBase64 = Convert.ToBase64String(blockIdBytes);
Console.WriteLine(blockIdBase64);
Which prints out (in LINQPad):
Byte[] (4 items)
| 136 |
| 19 |
| 0 |
| 0 |
iBMAAA==
In Qt/C++ I tried a few aporaches, all of them returning the wrong value.
const int a = 5000;
QByteArray b;
for(int i = 0; i != sizeof(a); ++i) {
b.append((char)(a&(0xFF << i) >>i));
}
qDebug() << b.toBase64(); // "iIiIiA=="
qDebug() << QByteArray::number(a).toBase64(); // "NTAwMA=="
qDebug() << QString::number(a).toUtf8().toBase64(); // "NTAwMA=="
How can I get the same result as the C# version?
See my comment for the problem with your for loop. It's shifting by one bit more each pass, but actually it should be 8 bits. Personally, I prefer this to a loop:
b.append(static_cast<char>(a >> 24));
b.append(static_cast<char>((a >> 16) & 0xff));
b.append(static_cast<char>((a >> 8) & 0xff));
b.append(static_cast<char>(a & 0xff));
The code above is for network standard byte order (big endian). Flip the order of the four operations from last to first for little endian byte order.
I ended up doing the following:
QByteArray temp;
int blockId = 5000;
for(int i = 0; i != sizeof(blockId); i++) {
temp.append((char)(blockId >> (i * 8)));
}
qDebug() << temp.toBase64(); // "iBMAAA==" which is correct
I think this would be clearer, though may be claimed to be ill styled...
int i = 0x01020304;
char (&bytes)[4] = (char (&)[4])i;
and you can access each byte directly with bytes[0], bytes[1], ... and do what ever you want to do with them.

Bitconverter for Java

Following the advice provided in the question https://stackoverflow.com/questions/1738244/what-is-the-java-equivalent-of-net-bitconverter I have begun implementing my own bitconverter for Java but am not getting equivalent results.
Could someone please guide me on what I might be doing incorrectly?
public static byte[] GetBytes(Integer value) {
ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
DataOutputStream stream = new DataOutputStream(byteStream);
try {
stream.writeInt(value);
} catch (IOException e) {
return new byte[4];
}
return byteStream.toByteArray();
}
byte[] result = BitConverter.GetBytes(1234); //JAVA: [0, 0, 4, -46]
byte[] result = BitConverter.GetBytes(1234); //C#: [210, 4, 0, 0]
That is just endianness (-46 and 210 is because of Java's signed bytes, but that is just a UI thing). Either reverse the array contents, or use shift operations to write the int.
Note: the endianness that .NET emits depends on the platform. I would suggest using KNOWN ENDIANNESS in both cases; most likely by using shift operations from both. Or perhaps a better idea: just use a pre-canned, platform independent serialization format (for example: protocol buffers, which has good support on both Java and .NET/C#).
For example; if I was writing an int value to a byte[] buffer (starting at offset), I might use:
buffer[offset++] = (byte)value;
buffer[offset++] = (byte)(value>>8);
buffer[offset++] = (byte)(value>>16);
buffer[offset++] = (byte)(value>>24);
this is guaranteed little-endian, and similar code should work on any framework.
The C# BitConverter will use the endianness of the underlying achitecture. In most environments, it will be little-endian (as it is in your case). Java's DataOutputStream however will always write in big-endian ("the portable way"). You'll need to check the endianness of the machine and write accordingly if you want to match the behavior.
Also, bytes in java are signed so the output is just a cosmetic difference. The bit representation is the same so you don't need to worry about that.
To check the endianness of your machine, use the java.nio.ByteOrder.nativeOrder() method. Then use the java.nio.ByteBuffer instead where you may specify the byte order() and write the data.
You could then implement your method like this:
public static byte[] GetBytes(int value)
{
ByteBuffer buffer = ByteBuffer.allocate(4).order(ByteOrder.nativeOrder());
buffer.putInt(value);
return buffer.array();
}
if any body need..C# to JAVA BitConverter.ToInt32
public static int toInt32_2(byte[] bytes, int index)
{
int a = (int)((int)(0xff & bytes[index]) << 32 | (int)(0xff & bytes[index + 1]) << 40 | (int)(0xff & bytes[index + 2]) << 48 | (int)(0xff & bytes[index + 3]) << 56);
// int a = (int)((int)(0xff & bytes[index]) << 56 | (int)(0xff & bytes[index + 1]) << 48 | (int)(0xff & bytes[index + 2]) << 40 | (int)(0xff & bytes[index + 3]) << 32);
//Array.Resize;
return a;
}
Also Int16
public static short toInt16(byte[] bytes, int index) //throws Exception
{
return (short)((bytes[index + 1] & 0xFF) | ((bytes[index] & 0xFF) << 0));
//return (short)(
// (0xff & bytes[index]) << 8 |
// (0xff & bytes[index + 1]) << 0
//);
}
BitConverter.getBytes
public static byte[] GetBytesU16(long value)
{
ByteBuffer buffer = ByteBuffer.allocate(8).order(ByteOrder.nativeOrder());
buffer.putLong(value);
return buffer.array();
}
Building on Jeff's answer, you can use a single ByteBuffer to convert both to and from int and byte[]. Here is code you can drop into a class to convert to/from Little Endian:
ByteBuffer _intShifter = ByteBuffer.allocate(Integer.SIZE / Byte.SIZE)
.order(ByteOrder.LITTLE_ENDIAN);
public byte[] intToByte(int value) {
_intShifter.clear();
_intShifter.putInt(value);
return _intShifter.array();
}
public int byteToInt(byte[] data)
{
_intShifter.clear();
_intShifter.put(data, 0, Integer.SIZE / Byte.SIZE);
_intShifter.flip();
return _intShifter.getInt();
}

Reading an unsigned 24-bit integer from a C# stream

What is the best way to read an unsigned 24-bit integer from a C# stream using BinaryReader?
So far I used something like this:
private long ReadUInt24(this BinaryReader reader)
{
try
{
return Math.Abs((reader.ReadByte() & 0xFF) * 256 * 256 + (reader.ReadByte() & 0xFF) * 256 + (reader.ReadByte() & 0xFF));
}
catch
{
return 0;
}
}
Is there any better way to do this?
Some quibbles with your code
You question and signature say unsigned but you return a signed value from the function
Byte in .Net is unsigned but you're using signed values for arithmetic forcing a later use of Math.Abs. Use all unsigned calculations to avoid this.
IMHO it's cleaner to shift bits using shift operators instead of multiplication.
Silently catching the exception is likely the wrong idea here.
I think it's more readable to do the following
private static uint ReadUInt24(this BinaryReader reader) {
try {
var b1 = reader.ReadByte();
var b2 = reader.ReadByte();
var b3 = reader.ReadByte();
return
(((uint)b1) << 16) |
(((uint)b2) << 8) |
((uint)b3);
}
catch {
return 0u;
}
}
This looks pretty elegant to me.
private static long ReadUInt24(this BinaryReader reader)
{
try
{
byte[] buffer = new byte[4];
reader.Read(buffer, 0, 3);
return (long)BitConverter.ToUInt32(buffer, 0);
}
catch
{
// Swallowing the exception here might not be a good idea, but that is a different topic.
return 0;
}
}

Convert a C printf(%c) to C#

I'm trying to convert this C printf to C#
printf("%c%c",(x>>8)&0xff,x&0xff);
I've tried something like this:
int x = 65535;
char[] chars = new char[2];
chars[0] = (char)(x >> 8 & 0xFF);
chars[1] = (char)(x & 0xFF);
But I'm getting different results.
I need to write the result to a file
so I'm doing this:
tWriter.Write(chars);
Maybe that is the problem.
Thanks.
In .NET, char variables are stored as unsigned 16-bit (2-byte) numbers ranging in value from 0 through 65535. So use this:
int x = (int)0xA0FF; // use differing high and low bytes for testing
byte[] bytes = new byte[2];
bytes[0] = (byte)(x >> 8); // high byte
bytes[1] = (byte)(x); // low byte
If you're going to use a BinaryWriter than just do two writes:
bw.Write((byte)(x>>8));
bw.Write((byte)x);
Keep in mind that you just performed a Big Endian write. If this is to be read as an 16-bit integer by something that expects it in Little Endian form, swap the writes around.
Ok,
I got it using the Mitch Wheat suggestion and changing the TextWriter to BinaryWriter.
Here is the code
System.IO.BinaryWriter bw = new System.IO.BinaryWriter(System.IO.File.Open(#"C:\file.ext", System.IO.FileMode.Create));
int x = 65535;
byte[] bytes = new byte[2];
bytes[0] = (byte)(x >> 8);
bytes[1] = (byte)(x);
bw.Write(bytes);
Thanks to everyone.
Especially to Mitch Wheat.

Categories