在 C# 中附加两个或多个字节数组
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/895120/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Append two or more byte arrays in C#
提问by torial
Is there a best (see below) way to append two byte arrays in C#?
有没有最好的(见下文)方法在 C# 中附加两个字节数组?
Pretending I have complete control, I can make the first byte array sufficiently large to hold the second byte array at the end and use the Array.CopyTofunction. Or I can loop over individual bytes and make an assignment.
假装我有完全的控制权,我可以使第一个字节数组足够大以容纳最后的第二个字节数组并使用Array.CopyTo函数。或者我可以遍历单个字节并进行分配。
Are there better ways? I can't imagine doing something like converting the byte arrays to string and joining them and converting them back would be better than either method above.
有更好的方法吗?我无法想象将字节数组转换为字符串并加入它们并将它们转换回来会比上面的任何一种方法都好。
In terms of best/better (in order):
在最佳/更好(按顺序)方面:
- Fastest
- Least RAM consumption
- 最快的
- 最少的内存消耗
A constraint is that I must work in the .NET 2.0 framework.
一个限制是我必须在 .NET 2.0 框架中工作。
The two choices recommended are MemoryStream and BlockCopy. I have run a simple speed test of 10,000,000 loops 3 times and got the following results:
推荐的两个选择是 MemoryStream 和 BlockCopy。我已经运行了 3 次 10,000,000 次循环的简单速度测试,并得到以下结果:
Average of 3 runs of 10,000,000 loops in milliseconds:
3 次运行 10,000,000 次循环的平均值(以毫秒为单位):
- BlockCopy Time: 1154, with a range of 13 milliseconds
- MemoryStream GetBuffer Time: 1470, with a range of 14 milliseconds
- MemoryStream ToArray Time: 1895, with a range of 3 milliseconds
- CopyTo Time: 2079, with a range of 19 milliseconds
- Byte-by-byte Time: 2203, with a range of 10 milliseconds
- BlockCopy 时间:1154,范围为 13 毫秒
- MemoryStream GetBuffer Time:1470,范围14毫秒
- MemoryStream ToArray 时间:1895,范围为 3 毫秒
- CopyTo 时间:2079,范围为 19 毫秒
- 逐字节时间:2203,范围为10毫秒
Results of List<byte> AddRangeover 10 million loops: List<byte> Time: 16694
List<byte> AddRange超过 1000 万次循环的结果:List<byte> 时间:16694
Relative RAM Consumption (1 is baseline, higher is worse):
相对 RAM 消耗(1 是基线,越高越差):
- Byte-by-byte: 1
- BlockCopy: 1
- Copy To: 1
- MemoryStream GetBuffer: 2.3
- MemoryStream ToArray: 3.3
- List<byte>: 4.2
- 逐字节:1
- 块复制:1
- 复制到:1
- 内存流获取缓冲区:2.3
- MemoryStream ToArray:3.3
- 列表<字节>:4.2
The test shows that in general, unless you are doing a lot of byte copies [which I am], looking at byte copies is not worth a focus [e.g. 10 million runs yielding a difference of as much as 1.1 seconds].
测试表明,一般来说,除非您进行大量字节复制 [我就是这样] ,否则查看字节副本不值得关注 [例如 1000 万次运行产生多达 1.1 秒的差异]。
采纳答案by dss539
You want BlockCopy
你想要BlockCopy
According to this blog postit is faster than Array.CopyTo.
根据这篇博客文章,它比 Array.CopyTo 更快。
回答by Nate
Your first option of making the first array large enough to contain the second array and using Array.CopyTo ends up being roughly the same as manually iterating over each item and making the assignment. Array.CopyTo() just makes it more concise.
使第一个数组足够大以包含第二个数组并使用 Array.CopyTo 的第一个选项最终与手动迭代每个项目并进行分配大致相同。Array.CopyTo() 只是让它更简洁。
Converting to string and back to array will be horribly slow in contrast to the above. And would likely use more memory.
与上述相比,转换为字符串并返回数组将非常缓慢。并且可能会使用更多内存。
回答by Joel Coehoorn
If you have arrays where the size will change from time to time, you're probably better off using a List<T>
in the first place. Then you can just call the AddRange()
method of the list.
如果您有大小不时变化的数组,那么您最好List<T>
首先使用 a 。然后你可以调用AddRange()
列表的方法。
Otherwise, Array.Copy() or Array.CopyTo() are as good as anything else you're likely to see.
否则,Array.Copy() 或 Array.CopyTo() 与您可能会看到的任何其他东西一样好。
回答by Joel Mueller
Another option, although I haven't tested it to see how it fares in terms of speed and memory consumption, would the LINQ approach:
另一种选择,虽然我没有测试过它在速度和内存消耗方面的表现如何,LINQ 方法是否:
byte[] combined = bytesOne.Concat(bytesTwo).Concat(bytesThree).ToArray();
...where bytesOne, bytesTwo, and bytesThree are byte arrays. Since Concat uses deferred execution, this shouldn't create any intermediate arrays, and it shouldn't duplicate the original arrays until it constructs the final merged array at the end.
...其中 bytesOne、bytesTwo 和 bytesThree 是字节数组。由于 Concat 使用延迟执行,因此不应创建任何中间数组,并且在最后构造最终合并数组之前不应复制原始数组。
Edit: LINQBridgewill allow you to use LINQ-to-Objects (which this is an example of) in the 2.0 framework. I understand if you don't want to depend on this, but it's an option.
编辑:LINQBridge将允许您在 2.0 框架中使用 LINQ-to-Objects(这是一个示例)。我理解您是否不想依赖于此,但这是一种选择。
回答by AndrewB
Have you taught about using List or ArrayList instead of an Array? With these types they can grow or shrink and append via InsertRange
你有没有教过使用 List 或 ArrayList 而不是 Array?使用这些类型,它们可以通过 InsertRange 增长或缩小和追加
回答by Jeff Moser
Create a new MemoryStreampassing into the constructor a buffer that's exactly the size of the merged one. Write the individual arrays, and then finally use the buffer:
创建一个新的MemoryStream ,将一个缓冲区传递给构造函数,该缓冲区的大小与合并的缓冲区大小完全相同。写入单个数组,然后最后使用缓冲区:
byte[] deadBeef = new byte[] { 0xDE, 0xAD, 0xBE, 0xEF};
byte[] baadF00d = new byte[] { 0xBA, 0xAD, 0xF0, 0x0D};
int newSize = deadBeef.Length + baadF00d.Length;
var ms = new MemoryStream(new byte[newSize], 0, newSize, true, true);
ms.Write(deadBeef, 0, deadBeef.Length);
ms.Write(baadF00d, 0, baadF00d.Length);
byte[] merged = ms.GetBuffer();
A lot of the low-level I/O functions in .NET take byte arrays and offsets. This was done to prevent needless copies. Be sure you really need the merged array if this is performance sensitive, otherwise just use buffers and offsets.
.NET 中的许多低级 I/O 函数采用字节数组和偏移量。这样做是为了防止不必要的复制。如果这对性能敏感,请确保您确实需要合并的数组,否则只需使用缓冲区和偏移量。
回答by Arjan Einbu
Do you need the output to actually be a byte array?
你需要输出实际上是一个字节数组吗?
If not, you could create yourself a "smart cursor" (which is similar to what LINQ does): Create a custom IEnumerator<byte> that will first iterate the first array, and just continue on the second one without interuption.
如果没有,您可以为自己创建一个“智能光标”(类似于 LINQ 所做的):创建一个自定义 IEnumerator<byte> ,它将首先迭代第一个数组,然后继续第二个数组而不会中断。
This would work in the 2.0 framework be fast (in that the joining of arrays has virtually no cost), and use no more RAM than the arrays already consume.
这将在 2.0 框架中快速运行(因为数组的加入几乎没有成本),并且使用的 RAM 不会超过数组已经消耗的内存。
回答by flq
You could also use an approach with a MemoryStream. Suppose b1 and b2 are two byte arrays, you can get a new one, b3, by using the MemoryStream in the following fashion:
您还可以使用 MemoryStream 的方法。假设 b1 和 b2 是两个字节数组,您可以通过以下方式使用 MemoryStream 获得一个新的 b3:
var s = new MemoryStream();
s.Write(b1, 0, b1.Length);
s.Write(b2, 0, b2.Length);
var b3 = s.ToArray();
This should work without LINQ and is in fact quite a bit faster.
这应该可以在没有 LINQ 的情况下工作,而且实际上要快得多。