在 C# 中组合两个或多个字节数组的最佳方法 [英] Best way to combine two or more byte arrays in C#
问题描述
我在 C# 中有 3 个字节数组,我需要将它们合并为一个.完成此任务的最有效方法是什么?
I have 3 byte arrays in C# that I need to combine into one. What would be the most efficient method to complete this task?
推荐答案
对于原始类型(包括字节),请使用 System.Buffer.BlockCopy
而不是 System.Array.Copy
.它更快.
For primitive types (including bytes), use System.Buffer.BlockCopy
instead of System.Array.Copy
. It's faster.
我使用 3 个每个 10 字节的数组对循环中的每个建议方法进行计时 100 万次.结果如下:
I timed each of the suggested methods in a loop executed 1 million times using 3 arrays of 10 bytes each. Here are the results:
- 使用
System.Array.Copy
的新字节数组 - 0.2187556 秒 - 使用
System.Buffer.BlockCopy
的新字节数组 - 0.1406286 秒 - IEnumerable
使用 C# yield 运算符 - 0.0781270 秒 - IEnumerable
使用 LINQ 的 Concat<> - 0.0781270 秒
- New Byte Array using
System.Array.Copy
- 0.2187556 seconds - New Byte Array using
System.Buffer.BlockCopy
- 0.1406286 seconds - IEnumerable<byte> using C# yield operator - 0.0781270 seconds
- IEnumerable<byte> using LINQ's Concat<> - 0.0781270 seconds
我将每个数组的大小增加到 100 个元素并重新运行测试:
I increased the size of each array to 100 elements and re-ran the test:
- 使用
System.Array.Copy
的新字节数组 - 0.2812554 秒 - 使用
System.Buffer.BlockCopy
的新字节数组 - 0.2500048 秒 - IEnumerable
使用 C# yield 运算符 - 0.0625012 秒 - IEnumerable
使用 LINQ 的 Concat<> - 0.0781265 秒
- New Byte Array using
System.Array.Copy
- 0.2812554 seconds - New Byte Array using
System.Buffer.BlockCopy
- 0.2500048 seconds - IEnumerable<byte> using C# yield operator - 0.0625012 seconds
- IEnumerable<byte> using LINQ's Concat<> - 0.0781265 seconds
我将每个数组的大小增加到 1000 个元素并重新运行测试:
I increased the size of each array to 1000 elements and re-ran the test:
- 使用
System.Array.Copy
的新字节数组 - 1.0781457 秒 - 使用
System.Buffer.BlockCopy
的新字节数组 - 1.0156445 秒 - IEnumerable
使用 C# yield 运算符 - 0.0625012 秒 - IEnumerable
使用 LINQ 的 Concat<> - 0.0781265 秒
- New Byte Array using
System.Array.Copy
- 1.0781457 seconds - New Byte Array using
System.Buffer.BlockCopy
- 1.0156445 seconds - IEnumerable<byte> using C# yield operator - 0.0625012 seconds
- IEnumerable<byte> using LINQ's Concat<> - 0.0781265 seconds
最后,我将每个数组的大小增加到 100 万个元素并重新运行测试,每个循环仅执行 4000 次:
Finally, I increased the size of each array to 1 million elements and re-ran the test, executing each loop only 4000 times:
- 使用
System.Array.Copy
的新字节数组 - 13.4533833 秒 - 使用
System.Buffer.BlockCopy
的新字节数组 - 13.1096267 秒 - IEnumerable
使用 C# yield 运算符 - 0 秒 - IEnumerable
使用 LINQ 的 Concat<> - 0 秒
- New Byte Array using
System.Array.Copy
- 13.4533833 seconds - New Byte Array using
System.Buffer.BlockCopy
- 13.1096267 seconds - IEnumerable<byte> using C# yield operator - 0 seconds
- IEnumerable<byte> using LINQ's Concat<> - 0 seconds
因此,如果您需要一个新的字节数组,请使用
So, if you need a new byte array, use
byte[] rv = new byte[a1.Length + a2.Length + a3.Length];
System.Buffer.BlockCopy(a1, 0, rv, 0, a1.Length);
System.Buffer.BlockCopy(a2, 0, rv, a1.Length, a2.Length);
System.Buffer.BlockCopy(a3, 0, rv, a1.Length + a2.Length, a3.Length);
但是,如果您可以使用 IEnumerable
,DEFINITELY 更喜欢 LINQ 的 Concat<> 方法.它只比 C# 的 yield 操作符慢一点,但更简洁、更优雅.
But, if you can use an IEnumerable<byte>
, DEFINITELY prefer LINQ's Concat<> method. It's only slightly slower than the C# yield operator, but is more concise and more elegant.
IEnumerable<byte> rv = a1.Concat(a2).Concat(a3);
如果您有任意数量的数组并使用 .NET 3.5,您可以使 System.Buffer.BlockCopy
解决方案更通用,如下所示:
If you have an arbitrary number of arrays and are using .NET 3.5, you can make the System.Buffer.BlockCopy
solution more generic like this:
private byte[] Combine(params byte[][] arrays)
{
byte[] rv = new byte[arrays.Sum(a => a.Length)];
int offset = 0;
foreach (byte[] array in arrays) {
System.Buffer.BlockCopy(array, 0, rv, offset, array.Length);
offset += array.Length;
}
return rv;
}
*注意:上面的块需要你在顶部添加以下命名空间才能工作.
*Note: The above block requires you adding the following namespace at the the top for it to work.
using System.Linq;
对于 Jon Skeet 关于后续数据结构迭代的观点(字节数组与 IEnumerable<byte>),我重新运行了最后一次计时测试(100 万个元素,4000 次迭代),添加了一个循环来遍历整个每次通过的数组:
To Jon Skeet's point regarding iteration of the subsequent data structures (byte array vs. IEnumerable<byte>), I re-ran the last timing test (1 million elements, 4000 iterations), adding a loop that iterates over the full array with each pass:
- 使用
System.Array.Copy
的新字节数组 - 78.20550510 秒 - 使用
System.Buffer.BlockCopy
的新字节数组 - 77.89261900 秒 - IEnumerable
使用 C# yield 运算符 - 551.7150161 秒 - IEnumerable
使用 LINQ 的 Concat<> - 448.1804799 秒
- New Byte Array using
System.Array.Copy
- 78.20550510 seconds - New Byte Array using
System.Buffer.BlockCopy
- 77.89261900 seconds - IEnumerable<byte> using C# yield operator - 551.7150161 seconds
- IEnumerable<byte> using LINQ's Concat<> - 448.1804799 seconds
关键是,了解结果数据结构的创建和使用的效率非常很重要.仅仅关注创建的效率可能会忽略与使用相关的低效率.感谢乔恩.
The point is, it is VERY important to understand the efficiency of both the creation and the usage of the resulting data structure. Simply focusing on the efficiency of the creation may overlook the inefficiency associated with the usage. Kudos, Jon.
这篇关于在 C# 中组合两个或多个字节数组的最佳方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!