Mat*_*vis 317
对于原始类型(包括字节),请使用System.Buffer.BlockCopy而不是System.Array.Copy.它更快.
我使用3个10字节的数组,在一个循环中执行了100万次的每个建议方法.结果如下:
System.Array.Copy - 0.2187556秒System.Buffer.BlockCopy - 0.1406286秒我将每个数组的大小增加到100个元素并重新运行测试:
System.Array.Copy - 0.2812554秒System.Buffer.BlockCopy - 0.2500048秒我将每个数组的大小增加到1000个元素并重新运行测试:
System.Array.Copy - 1.0781457秒System.Buffer.BlockCopy - 1.0156445秒最后,我将每个数组的大小增加到100万个元素并重新运行测试,每个循环只执行4000次:
System.Array.Copy - 13.4533833秒System.Buffer.BlockCopy - 13.1096267秒因此,如果您需要一个新的字节数组,请使用
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);
Run Code Online (Sandbox Code Playgroud)
但是,如果你可以使用IEnumerable<byte>,那么DEFINITELY更喜欢LINQ的Concat <>方法.它只比C#yield运算符略慢,但更简洁,更优雅.
IEnumerable<byte> rv = a1.Concat(a2).Concat(a3);
Run Code Online (Sandbox Code Playgroud)
如果你有任意数量的数组并使用.NET 3.5,你可以使System.Buffer.BlockCopy解决方案更通用,如下所示:
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;
}
Run Code Online (Sandbox Code Playgroud)
*注意:上面的块要求您在顶部添加以下命名空间才能工作.
using System.Linq;
Run Code Online (Sandbox Code Playgroud)
对于Jon Skeet关于后续数据结构迭代(字节数组与IEnumerable <byte>)的观点,我重新运行了最后的定时测试(100万个元素,4000次迭代),添加了一个遍历整个数组的循环通过:
System.Array.Copy - 78.20550510秒System.Buffer.BlockCopy - 77.89261900秒关键是,理解结果数据结构的创建和使用的效率非常重要.仅仅关注创建的效率可能会忽略与使用相关的低效率.荣誉,乔恩.
Jon*_*eet 146
在我看来,许多答案都忽略了规定的要求:
这两个一起排除了一个LINQ字节序列 - 任何东西yield都会使得无法在不迭代整个序列的情况下获得最终大小.
如果那些当然不是真正的要求,LINQ可能是一个非常好的解决方案(或IList<T>实现).但是,我会假设Superdumbell知道他想要什么.
(编辑:我刚才有另外一个想法.制作数组副本和懒散地阅读它们之间存在很大的语义差异.考虑一下如果在调用Combine(或者其他)之后更改其中一个"源"数组中的数据会发生什么)方法但在使用结果之前 - 使用延迟评估,该变化将是可见的.使用立即复制,它不会.不同的情况将要求不同的行为 - 只需注意一些事情.)
以下是我提出的方法 - 与其他一些答案中包含的方法非常相似,当然:)
public static byte[] Combine(byte[] first, byte[] second)
{
byte[] ret = new byte[first.Length + second.Length];
Buffer.BlockCopy(first, 0, ret, 0, first.Length);
Buffer.BlockCopy(second, 0, ret, first.Length, second.Length);
return ret;
}
public static byte[] Combine(byte[] first, byte[] second, byte[] third)
{
byte[] ret = new byte[first.Length + second.Length + third.Length];
Buffer.BlockCopy(first, 0, ret, 0, first.Length);
Buffer.BlockCopy(second, 0, ret, first.Length, second.Length);
Buffer.BlockCopy(third, 0, ret, first.Length + second.Length,
third.Length);
return ret;
}
public static byte[] Combine(params byte[][] arrays)
{
byte[] ret = new byte[arrays.Sum(x => x.Length)];
int offset = 0;
foreach (byte[] data in arrays)
{
Buffer.BlockCopy(data, 0, ret, offset, data.Length);
offset += data.Length;
}
return ret;
}
Run Code Online (Sandbox Code Playgroud)
当然,"params"版本需要首先创建一个字节数组的数组,这会带来额外的低效率.
Nat*_*ini 37
为了代码清洁,我进一步采用了Matt的LINQ示例:
byte[] rv = a1.Concat(a2).Concat(a3).ToArray();
Run Code Online (Sandbox Code Playgroud)
就我而言,阵列很小,所以我不关心性能.
Fry*_*Guy 27
如果您只需要一个新的字节数组,请使用以下命令:
byte[] Combine(byte[] a1, byte[] a2, byte[] a3)
{
byte[] ret = new byte[a1.Length + a2.Length + a3.Length];
Array.Copy(a1, 0, ret, 0, a1.Length);
Array.Copy(a2, 0, ret, a1.Length, a2.Length);
Array.Copy(a3, 0, ret, a1.Length + a2.Length, a3.Length);
return ret;
}
Run Code Online (Sandbox Code Playgroud)
或者,如果您只需要一个IEnumerable,请考虑使用C#2.0 yield运算符:
IEnumerable<byte> Combine(byte[] a1, byte[] a2, byte[] a3)
{
foreach (byte b in a1)
yield return b;
foreach (byte b in a2)
yield return b;
foreach (byte b in a3)
yield return b;
}
Run Code Online (Sandbox Code Playgroud)
00j*_*0jt 10
我实际上遇到了使用Concat的一些问题...(在1000万的阵列中,它实际上已经崩溃了).
我发现以下内容简单,容易并且运行良好而不会崩溃,它适用于任意数量的数组(不仅仅是三个)(它使用LINQ):
public static byte[] ConcatByteArrays(params byte[][] arrays)
{
return arrays.SelectMany(x => x).ToArray();
}
Run Code Online (Sandbox Code Playgroud)
memorystream类对我来说非常好.我无法让缓冲类以与memorystream一样快的速度运行.
using (MemoryStream ms = new MemoryStream())
{
ms.Write(BitConverter.GetBytes(22),0,4);
ms.Write(BitConverter.GetBytes(44),0,4);
ms.ToArray();
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
258079 次 |
| 最近记录: |