我如何从字节数组中删除多个字节?
答案 0 :(得分:25)
编辑:正如nobugz的评论(和Reed Copsey的回答)提到的,如果你实际上不需要将结果作为字节数组,你应该考虑使用ArraySegment<T>
:
ArraySegment<byte> segment = new ArraySegment<byte>(full, 16, full.Length - 16);
否则,必须进行复制 - 数组总是具有固定大小,因此您无法从现有数组中“删除”前16个字节。相反,您必须创建一个新的较小的数组并将相关数据复制到其中。
Zach的建议是非LINQ方法的正确行,但它可以变得更简单(假设您已经知道原始数组至少有16个字节):
byte[] newArray = new byte[oldArray.Length - 16];
Buffer.BlockCopy(oldArray, 16, newArray, 0, newArray.Length);
或
byte[] newArray = new byte[oldArray.Length - 16];
Array.Copy(oldArray, 16, newArray, 0, newArray.Length);
我怀疑 Buffer.BlockCopy
会稍快一些,但我不确定。
请注意,如果涉及的数组很大,这两者都可能比LINQ方法更有效:LINQ方法要求从迭代器单独返回每个字节,并且可能以相同的方式生成中间副本因为向List<T>
添加项目需要定期增长后备阵列。显然不要进行微优化,但如果这段代码是性能瓶颈,则值得检查。
Buffer.BlockCopy
和Array.Copy
- 它们非常接近 - 但LINQ方法慢了100多倍。
在我的笔记本电脑上,使用10,000个元素的字节数组,使用LINQ执行40,000个拷贝花了近10秒钟;上述方法花费大约80ms来完成相同的工作量。我将迭代次数增加到4,000,000,它仍然只用了大约7秒。显然,微基准测试的常规警告适用,但这是一个非常显着的差异。
如果这是在对性能很重要的代码路径中,请务必使用上述方法:)
答案 1 :(得分:17)
你可以这样做:
using System.Linq
// ...
var newArray = oldArray.Skip(numBytes).ToArray();
答案 2 :(得分:6)
我还要提到 - 根据您计划如何使用结果,通常,另一种方法是使用ArraySegment<T>
来访问数组的剩余部分。这可以防止复制数组的需要,这在某些使用场景中可能更有效:
ArraySegment<byte> segment = new ArraySegment<byte>(originalArray, 16, originalArray.Length-16);
// Use segment how you'd use your array...
答案 3 :(得分:0)
如果你不能使用Linq,你可以这样做:
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
您还需要处理数组长度小于16个字节的情况。