C# multi-dim to one-dim arrays

Started by
8 comments, last by Lutz 16 years, 7 months ago
Is there a way to cast or copy a byte[,] to a byte[]? For instance, I have byte[,] data = new byte[10,10]; // Fill data Can I cast data to a byte[100] or copy data to byte[] flatData = new byte[100] ? Thanks, Lutz
Advertisement
This should do what you need.

public static void MultiArrayToSingle(byte[,]multi , byte[] single){     int x = multi.GetLength(0);     int y = multi.Length / x;     if (single.Length < x * y)     {         throw new Exception("Not enough room in the array");     }     for (int b = 0; b < y; b++)     {         for (int a = 0; a < x; a++)         {             single[a + (b*x)] = multi[a, b];         }     }}


Hope that helps.
theTroll
Yeah, that works, but I search for a way where I don't have to copy the array by manually. I think byte[,] is laid out as a flat array in memory anyway, so I wondered if there is a way to simply cast it to a byte[].

Also, what I just ran into, when I want to write a float[,] array with a binary writer, I tried to copy the array to a float[] array and write it, but BinaryWriter does not take float[], just byte[], so I'd have to write call the Write function for every single float, which is extremely inefficient. Is there a way to just get a pointer to the array, maybe by using unsafe code?
Is there a reason that you don't want to copy manually?

Is there a performance thing that I don't know about?

If it is something you don't do very often, then there is no reason to worry about doing it manually.

For some reason people think you always have to have an "perfect" solution when a brute force method is just as good for what they are doing.

theTroll
If you write some unsafe code that makes a pointer to your array you should be able to do exactly that.

byte *pArray = &(multiDimArray);
Quote:Original post by AntiRush
If you write some unsafe code that makes a pointer to your array you should be able to do exactly that.

byte *pArray = &(multiDimArray);


No, all that does is set pArray to the address of the multiDimArray. You didn't copy anything.

theTroll

I serialized into a zip stream directly and byte-by-byte, which was very inefficient. Instead, I use a memory stream now and additionally I copy the multidim array manually as TheTroll proposed and send the whole byte[] array to the stream.

Copying float arrays was a beast! I had to use BitConverter to convert each single float to an array of 4 bytes.

I think the code byte *pArray = &(multiDimArray); doesn't work since this would return a pointer to the memory location where the address of the array is stored, not to the array itself. The code

float[] multiDimArray = new float[10];
unsafe { byte* pArray = (byte*)multiDimArray; }

does not compile and says cannot convert float[] to byte*.

But anyway, I guess my problem is solved so far, even though the solution is not very elegant. Thanks again!
Use System.Buffer.BlockCopy

ie :
byte [,] source = new byte[10,10];byte [] dest = new byte[source.Length];// assume that you've filled source dataSystem.Buffer.BlockCopy(source, 0, dest, 0, source.Length);


so long as the source and dest are of the same type (eg, byte, float etc) it will work. (it will work otherwise - see below).

the length parameter is the number of bytes to copy - so if you're copying floats, you'll need to multiply the array length by 4 (the size of a float).

this function can also be used to copy the bytes of one type array into another - useful for getting at the bytes of an object. so long as the dest array has enough bytes (not indices). The dimensions of the source (or dest) dont matter - since they are just stored as a flat block in memory.

so in the final example you gave where you want to convert a float array to a byte array, you could do :
float [,] source = new float[10,10];byte [] dest = new byte[source.Length * 4];// assume that you've filled source dataSystem.Buffer.BlockCopy(source, 0, dest, 0, source.Length * 4);


Wyzfen
Buffer.BlockCopy seems like the "right" way to go. Just make sure you wrap it in a try catch to make sure you don't have some unhanded exceptions if you mess up the sizes. Nice find Wyzfen.

theTroll
That's exactly what I was looking for.
Thanks guys, you have been extremely helpful.

- Lutz

This topic is closed to new replies.

Advertisement