Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Remove First 16 Bytes?

Tags:

c#

bytearray

How would I go about removing a number of bytes from a byte array?

like image 383
cam Avatar asked Mar 27 '10 21:03

cam


3 Answers

EDIT: As nobugz's comment (and Reed Copsey's answer) mentions, if you don't actually need the result as a byte array, you should look into using ArraySegment<T>:

ArraySegment<byte> segment = new ArraySegment<byte>(full, 16, full.Length - 16);

Otherwise, copying will be necessary - arrays always have a fixed size, so you can't "remove" the first 16 bytes from the existing array. Instead, you'll have to create a new, smaller array and copy the relevant data into it.

Zach's suggestion is along the right lines for the non-LINQ approach, but it can be made simpler (this assumes you already know the original array is at least 16 bytes long):

byte[] newArray = new byte[oldArray.Length - 16];
Buffer.BlockCopy(oldArray, 16, newArray, 0, newArray.Length);

or

byte[] newArray = new byte[oldArray.Length - 16];
Array.Copy(oldArray, 16, newArray, 0, newArray.Length);

I suspect Buffer.BlockCopy will be slightly faster, but I don't know for sure.

Note that both of these could be significantly more efficient than the LINQ approach if the arrays involved are big: the LINQ approach requires each byte to be individually returned from an iterator, and potentially intermediate copies to be made (in the same way as adding items to a List<T> needs to grow the backing array periodically). Obviously don't micro-optimise, but it's worth checking if this bit of code is a performance bottleneck.

EDIT: I ran a very "quick and dirty" benchmark of the three approaches. I don't trust the benchmark to distinguish between Buffer.BlockCopy and Array.Copy - they were pretty close - but the LINQ approach was over 100 times slower.

On my laptop, using byte arrays of 10,000 elements, it took nearly 10 seconds to perform 40,000 copies using LINQ; the above approaches took about 80ms to do the same amount of work. I upped the iteration count to 4,000,000 and it still only took about 7 seconds. Obviously the normal caveats around micro-benchmarks apply, but this is a pretty significat difference.

Definitely use the above approach if this is in a code path which is important to performance :)

like image 91
Jon Skeet Avatar answered Nov 04 '22 14:11

Jon Skeet


You could do this:

using System.Linq

// ...

var newArray = oldArray.Skip(numBytes).ToArray();
like image 27
Jacob Avatar answered Nov 04 '22 15:11

Jacob


I will also mention - depending on how you plan to use the results, often, an alternative approach is to use ArraySegment<T> to just access the remaining portion of the array. This prevents the need to copy the array, which can be more efficient in some usage scenarios:

ArraySegment<byte> segment = new ArraySegment<byte>(originalArray, 16, originalArray.Length-16);

// Use segment how you'd use your array...  
like image 6
Reed Copsey Avatar answered Nov 04 '22 16:11

Reed Copsey