连接byte 的C#列表

我正在创建几个需要连接在一起创建一个大字节数组的字节数组 – 我宁愿不使用byte [],但在这里别无选择……

我在创建它们时将每个添加到List中,所以我只需要在拥有所有byte []后进行连接,但我的问题是,实际执行此操作的最佳方法是什么?

当我有一个包含未知数量的byte []的列表时,我想将它们连在一起。

谢谢。

listOfByteArrs.SelectMany(byteArr=>byteArr).ToArray() 

上面的代码将一系列字节序列连接成一个序列 – 并将结果存储在一个数组中。

虽然可读,但这并不是最有效的 – 它没有利用你已经知道结果字节数组长度的事实,因此可以避免动态扩展的.ToArray()实现,它必然涉及多个分配和数组副本。 此外, SelectMany是根据迭代器实现的; 这意味着很多+很多接口调用很慢。 但是,对于小型数据集大小,这不太重要。

如果您需要更快的实施,您可以执行以下操作:

 var output = new byte[listOfByteArrs.Sum(arr=>arr.Length)]; int writeIdx=0; foreach(var byteArr in listOfByteArrs) { byteArr.CopyTo(output, writeIdx); writeIdx += byteArr.Length; } 

或者Martinho建议:

 var output = new byte[listOfByteArrs.Sum(arr => arr.Length)]; using(var stream = new MemoryStream(output)) foreach (var bytes in listOfByteArrs) stream.Write(bytes, 0, bytes.Length); 

一些时间:

 var listOfByteArrs = Enumerable.Range(1,1000) .Select(i=>Enumerable.Range(0,i).Select(x=>(byte)x).ToArray()).ToList(); 

使用短方法连接这些500500字节需要15ms,使用快速方法在我的机器上花费0.5ms – YMMV,并注意到对于许多应用程序来说两者都足够快;-)。

最后,您可以将Array.CopyTo替换为static Array.Copy ,低级Buffer.BlockCopy或具有预分配后备缓冲区的MemoryStream – 这些在我的测试(x64 .NET 4.0)上的执行情况非常相似。

这是一个基于Andrew Bezzub和fejesjoco答案的解决方案,预先分配所需的所有内存。 这产生Θ(N)存储器使用和Θ(N)时间(N是总字节数)。

 byte[] result = new byte[list.Sum(a => a.Length)]; using(var stream = new MemoryStream(result)) { foreach (byte[] bytes in list) { stream.Write(bytes, 0, bytes.Length); } } return result; 

将它们全部写入MemoryStream而不是列表。 然后调用MemoryStream.ToArray()。 或者当您有列表时,首先汇总所有字节数组长度,创建一个具有总长度的新字节数组,并将每个数组复制到大数组中的最后一个数组之后。

使用Linq:

  List list = new List(); list.Add(new byte[] { 1, 2, 3, 4 }); list.Add(new byte[] { 1, 2, 3, 4 }); list.Add(new byte[] { 1, 2, 3, 4 }); IEnumerable result = Enumerable.Empty(); foreach (byte[] bytes in list) { result = result.Concat(bytes); } byte[] newArray = result.ToArray(); 

也许更快的解决方案(不预先声明arrays):

 IEnumerable bytesEnumerable = GetBytesFromList(list); byte[] newArray = bytesEnumerable.ToArray(); private static IEnumerable GetBytesFromList(IEnumerable> list) { foreach (IEnumerable elements in list) { foreach (T element in elements) { yield return element; } } } 

看起来上面只会迭代每个数组一次。

您可以使用AddRange方法将每个字节数组直接添加到List ,而不是将每个字节数组存储到List

嗯list.addrange怎么样 ?