C# Big-endian ulong from 4 bytes
Asked Answered
S

7

19

Im trying to cast a 4 byte array to an ulong in C#. I'm currently using this code:

atomSize = BitConverter.ToUInt32(buffer, 0);

The byte[4] contains this:

0 0 0 32

However, the bytes are Big-Endian. Is there a simple way to convert this Big-Endian ulong to a Little-Endian ulong?

Sferics answered 20/7, 2010 at 21:47 Comment(0)
H
24

I believe that the EndianBitConverter in Jon Skeet's MiscUtil library (nuget link) can do what you want.

You could also swap the bits using bit shift operations:

uint swapEndianness(uint x)
{
    return ((x & 0x000000ff) << 24) +  // First byte
           ((x & 0x0000ff00) << 8) +   // Second byte
           ((x & 0x00ff0000) >> 8) +   // Third byte
           ((x & 0xff000000) >> 24);   // Fourth byte
}

Usage:

atomSize = BitConverter.ToUInt32(buffer, 0);
atomSize = swapEndianness(atomSize);
Heptachord answered 20/7, 2010 at 21:53 Comment(4)
Thanks, maybe you could show me what you are doing per line? That would be awesome, I've never used bit shifting until now.Sferics
@WesleyE: I've rewritten it to make it a little clearer. It handles one byte at a time, masks out the 8 bits and then shifts then into their new position. The four bytes are then added together to give the result. If you don't understand what bitshifting is, I recommend this question + answer: #142025Heptachord
It is faster to remove the and-operations and cast to byte each time.Courses
You can install MiscUtil via Nuget: nuget.org/packages/JonSkeet.MiscUtilTopography
M
10

In .net core (>= 2.1), you can use this instead:

BinaryPrimitives.ReadUInt32BigEndian(buffer);

That way, you're sure of the endianness you're reading from.

Documentation

It's implemented there in case you're wondering how it works

Edit: as mentionned by @smkanadl in the comments, it seems that you can use this API as well in .net framework by installing the System.Memory package.

Morbidity answered 5/4, 2019 at 14:14 Comment(2)
Best solution, because it doesn't require bit fiddling or additional iterations of the buffer (Array.Reverse()) or additional allocations (buffer.Reverse().ToArray()).Stalwart
This solution is not limited to .net core. You can simply install the System.Memory nuget package.Myiasis
W
7

System.Net.IPAddress.NetworkToHostOrder(atomSize); will flip your bytes.

Warga answered 20/7, 2010 at 22:0 Comment(2)
Not necessarily. If your host is already big-endian, no change will be made.Pennywise
Doesn't matter, Jeff.The point is,if the system is already big endian, then BitConverter would have read it as BigEndian and no change would be needed anyway.Unfortunately, using this function or Jon's convert can have some serious performance penalties, if say you are working with a file that contains hundreds of thousands of them.If this is the case then you should go with Mark Byers suggestion.The only way to get faster is to make CPU specific functions i.e. x86 has the BSWAP assembly instruction which is much faster than bit shifting. This function is perfectly fine for packet processingAixenprovence
D
5

I recommend using Mono's DataConvert which is like BitConverter on steroids. It allows you to read in big-endian byte arrays directly and improves massively on BitConverter.

A direct link to the source is here.

Doublespace answered 20/7, 2010 at 22:6 Comment(1)
Fixed source location (looks like they moved to github :D)Doublespace
P
4
BitConverter.ToUInt32(buffer.Reverse().ToArray(), 0)

No?

Polyp answered 18/8, 2012 at 18:28 Comment(2)
Not exactly, you'd need a ToArray() call there.Pennywise
Not quite the same thing, if your buffer is greater than 4, then you'll get the last bytes swapped instead. Instead of 0, buffer.Length-4.Aixenprovence
F
2

This may be old but I'm surprised no one came up with this simplest answer yet, only requires one line...

// buffer is 00 00 00 32
Array.Reverse(buffer);
// buffer is 32 00 00 00
atomSize = BitConverter.ToUInt32(buffer, 0);

I'm using it to compare checksums generated in C# (little-endian) with checksums generated in Java (big-endian).

Feud answered 6/3, 2015 at 17:9 Comment(2)
Not the same thing. if buffer is 00 00 00 32 54, then your buffer is after the reverse is 54 32 00 00 00, so a ToUInt32 will not give you the value 32. If your buffer is always length 4 then this will work just fine. To make it work it work for different lengths, you would need Length-4 instead of 0 after the Reverse.Aixenprovence
The topic is "C# Big-endian ulong from 4 bytes", and this was my answer specific to the question, I never said this was a solution for every case, but for defined numeric data types (16-bit, 32-bit, 64-bit, etc) it's sufficient as long as the target byte-array has the same number of bytes.Feud
A
0
firstSingle = BitConverter.ToSingle(buffer,0);
secondSingle = BitConverter.ToSingle(buffer,2); 

var result = BitConverter.ToUInt32(BitConverter.GetBytes(secondSingle).Concat(BitConverter.GetBytes(firstSingle).ToArray());
Adelaadelaida answered 21/6, 2012 at 10:53 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.