I am creating several byte arrays that need to be joined together to create one large byte array - i'd prefer not to use byte[]'s at all but have no choice here...
I am adding each one to a List as I create them, so I only have to do the concatenation once I have all the byte[]'s, but my question is, what is the best way of actually doing this?
When I have a list with an unknown number of byte[]'s and I want to concat them all together.
Thanks.
hmm how about list.addrange?
Use Linq:
Maybe faster solution would be (not declaring array upfront):
It seems like above would iterate each array only once.
write them all to a MemoryStream instead of a list. then call MemoryStream.ToArray(). Or when you have the list, first summarize all the byte array lengths, create a new byte array with the total length, and copy each array after the last in the big array.
Instead of storing each byte array into a
List<byte[]>
, you could instead add them directly to aList<byte>
, using the AddRange method for each one.Here's a solution based on Andrew Bezzub's and fejesjoco's answers, pre-allocating all the memory needed up front. This yields Θ(N) memory usage and Θ(N) time (N being the total number of bytes).
The above code will concatenate a sequence of sequences of bytes into one sequence - and store the result in an array.
Though readable, this is not maximally efficient - it's not making use of the fact that you already know the length of the resultant byte array and thus can avoid the dynamically extended
.ToArray()
implementation that necessarily involves multiple allocations and array-copies. Furthermore,SelectMany
is implemented in terms of iterators; this means lots+lots of interface calls which is quite slow. However, for small-ish data-set sizes this is unlikely to matter.If you need a faster implementation you can do the following:
or as Martinho suggests:
Some timings:
Using the short method to concatenate these 500500 bytes takes 15ms, using the fast method takes 0.5ms on my machine - YMMV, and note that for many applications both are more than fast enough ;-).
Finally, you could replace
Array.CopyTo
with thestatic
Array.Copy
, the low-levelBuffer.BlockCopy
, or aMemoryStream
with a preallocated back buffer - these all perform pretty much identically on my tests (x64 .NET 4.0).