Remove First 16 Bytes?

2019-01-27 23:49发布

问题:

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

回答1:

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 :)



回答2:

You could do this:

using System.Linq

// ...

var newArray = oldArray.Skip(numBytes).ToArray();


回答3:

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...  


回答4:

If you can't use Linq, you could do it this way:

byte[] myArray = // however you acquire the array

byte[] newArray = new byte[myArray.Length - 16];

for (int i = 0; i < newArray.Length; i++)
{
    newArray[i] = myArray[i + 16];
}

// newArray is now myArray minus the first 16 bytes

You'll also need to handle the case where the array is less than 16 bytes long.



标签: c# bytearray