How do I convert byte array to UInt32 array?
Asked Answered
H

7

6

Lets say In C++ I got code like this..

void * target
uint32 * decPacket = (uint32 *)target;

So in C# it would be like..

byte[] target;
UInt32[] decPacket = (UInt32[])target;

Cannot convert type byte[] to uint[]

How do I convert this memory aligning thing C++ does to arrays to C#?

Hampden answered 2/9, 2011 at 20:28 Comment(2)
I'll add that there is a dirty trick: #619541Unsphere
There's a better (and dirtier) trick which avoids iterations. See my answer below: https://mcmap.net/q/1609360/-how-do-i-convert-byte-array-to-uint32-arrayThessalonian
O
14

Well, something close would be to use Buffer.BlockCopy:

uint[] decoded = new uint[target.Length / 4];
Buffer.BlockCopy(target, 0, decoded, 0, target.Length);

Note that the final argument to BlockCopy is always the number of bytes to copy, regardless of the types you're copying.

You can't just treat a byte array as a uint array in C# (at least not in safe code; I don't know about in unsafe code) - but Buffer.BlockCopy will splat the contents of the byte array into the uint array... leaving the results to be determined based on the endianness of the system. Personally I'm not a fan of this approach - it leaves the code rather prone to errors when you move to a system with a different memory layout. I prefer to be explicit in my protocol. Hopefully it'll help you in this case though.

Orle answered 2/9, 2011 at 20:31 Comment(2)
helped in my case yup. Seems in C++ it never copy's anything though.. it just realigns from byte scan to two bytes at once. Atleast this solution avoids me using loops to do this process.Hampden
In unsafe code, you can sort of do it - you can fix the array and use pointer math to iterate through the byte array as uint pointers directly. It works well, but it's basically reverting to a C/C++/native approach...Dorren
T
2

You can have the cake (avoid allocations) and eat it too (avoid iterations), if you're willing to move to the dark side.

Check out my answer to a related question, in which I demonstrate how to convert float[] to byte[] and vice versa: What is the fastest way to convert a float[] to a byte[]?

Thessalonian answered 12/3, 2012 at 11:37 Comment(0)
D
1

As Jon mentioned, Buffer.BlockCopy will work well for copying this.

However, if this is an interop scenario, and you want to access the byte array directly as uint[], the closest you can do is to the C++ approach would be to use unsafe code:

byte[] target;
CallInteropMethod(ref target);

fixed(byte* t = target)
{
   uint* decPacket = (uint*)t;

   // You can use decPacket here the same way you do in C++
}

I personally prefer making the copy, but if you need to avoid actually copying the data, this does allow you to work (in an unsafe context).

Dorren answered 2/9, 2011 at 20:39 Comment(5)
wow awesome!.. I'll have to try this out! what is? CallInteropMethodHampden
@SSpoke: C#, in an unsafe context, can act very much like C++ - and get all that pointer goodness/nastiness back ;)Dorren
The CallInteropMethod was just saying "this is something to fill in the byte[]" - normally, this wouldn't be used in pure managed code...Dorren
Blah I thought about it.. and I was sick of C++.. that's why I am porting this to .NET.. so I'll keep it strictly C#.. without any unsafe code. (Honestly I am very confused :P I have to wrap all the brackets around all my logic? then I also have encPacket which also is bytes -> uint32 blah too complicated heheHampden
@SSpoke: Good call (unless this is perf. critical code) - I'd typically avoid this in all situations except those where I've profiled and discovered it's very, very difficult to handle otherwise without major implications.Dorren
E
1

I used BitConverter.ToUInt32() - https://learn.microsoft.com/en-us/dotnet/api/system.bitconverter.touint32?view=netcore-3.1

byte[] source = new byte[n];
UInt32 destination;

destination = BitConverter.ToUInt32(source, 0);

It seems to work fine for me.

Expressage answered 23/10, 2020 at 8:30 Comment(0)
T
0

You can use Buffer.BlockCopy. Rather than Array.Copy, BlockCopy does a byte-level copy without checking the array types are fully compatible.

Like so:

uint[] array = new uint[bytes.Length/4];
Buffer.BlockCopy(bytes, 0, array, 0, bytes.Length);
Treadway answered 2/9, 2011 at 20:32 Comment(2)
I am pretty sure if you do this, you will get an exception. "Offset and length were out of bounds for the array or count is greater than the number of elements from index to the end of the source collection"Conte
Why? The length to the argument to BlockCopy is specified in bytes.Treadway
J
0

Years late but maybe this will help someone else. (It's also kind of new.)

We can do a c++ style reinterpret cast (sort of) using the new Span<> in .Net Core 2.1 or later. There are no heap memory allocations so it is very fast.

Span<byte> byteArray = MemoryMarshal.AsBytes<uint>(uIntArray);
// with span we can get a byte, set a byte, iterate, and more.
byte someByte = byteSpan[2]; 
byteSpan[2] = 33;

If byte[] is needed, as stated in the question, then the above can be taken one step further. (This would allocate memory and copy but it is still fast.)

byte[] byteArray = MemoryMarshal.AsBytes<uint>(uIntArray).ToArray();
Jungly answered 14/5, 2022 at 1:58 Comment(1)
This converts the array the other way around. The original question was about converting FROM byte array TO uint array.Kutenai
A
-1

Loop over all array items and call Convert.ToUint32() on each of them.Here:

 Uint32[] res = new Uint32[target.Length];
 for(int i = 0;i <= target.Length;i++) 
 {
     res[i] = Convert.ToUint32(target[i]);
 }

Here is an official link from MSDN. http://msdn.microsoft.com/en-us/library/469cwstk.aspx

Annadiana answered 2/9, 2011 at 20:36 Comment(4)
will this even work? it will create as much UInt32's are there is byte's.. I have to make 2 bytes into 1 uint though.Hampden
I think new Uint32[target.length] has to be new Uint32[target.length / sizeof(UInt32)]Hampden
This requires using BitConverter if you want to loop. This will give you a unit with the value of the individual byte - which is very different...Dorren
Feel free to edit if you are sure that that is correct @SSpoke.I am always open for people willing to fix my mistakes.Annadiana

© 2022 - 2024 — McMap. All rights reserved.