C# concat双字节[]返回System.OutOfMemoryException

C# concat双字节[]返回System.OutOfMemoryException,c#,C#,我对concat双字节[]有问题。其中一个有超过300000000字节。它正在引发类型为System.OutOfMemoryException的异常 我使用以下代码: byte[] b3 = by2.Concat(by1).ToArray(); 任何人都可以帮我好吧,错误消息本身就存在,您没有~550Mb的连续可用RAM。也许它太支离破碎了。嗯。。你知道,从系统中要求一个600毫克的连续块-我并不惊讶。它本身是一个相当大的块,如果您的内存中还必须有源数组,那么就有超过1GB的原始数据块 您可能

我对concat双字节[]有问题。其中一个有超过300000000字节。它正在引发类型为
System.OutOfMemoryException
的异常

我使用以下代码:

byte[] b3 = by2.Concat(by1).ToArray();

任何人都可以帮我

好吧,错误消息本身就存在,您没有~550Mb的连续可用RAM。也许它太支离破碎了。

嗯。。你知道,从系统中要求一个600毫克的连续块-我并不惊讶。它本身是一个相当大的块,如果您的内存中还必须有源数组,那么就有超过1GB的原始数据块


您可能应该开始考虑其他数据结构,或者尝试将它们作为文件保存并映射到内存编辑:memmapping一个完整的文件需要地址空间中相同的连续区域,因此它解决不了任何问题。此答案将被删除。

因为
Concat
调用
ToArray
不知道结果数组必须有多大。它不能创建适当的大数组,而只是用数据填充它。所以它会创建一个小的,然后当它满的时候会创建一个新的,大小是原来的两倍,等等,只要有更多的数据需要填充。这样你需要比理论上的
(b1.Length+b2.Length)*2更多的内存。而且事情变得更加棘手,因为在某一点之后,这些大数组被分配到LOH上,并且不像普通对象那样容易被GC收集

这就是为什么在本例中不应使用
ToArray()
,而应使用老式的方法:分配大小等于的新数组合并源数组的大小并复制数据

比如:

var b3 = new byte[b1.Length + b2.Length];
Array.Copy(b1, b2, b1.Length);
Array.Copy(b1, 0, b2, b1.Length, b2.Length);

这并不能保证成功,但会使成功更有可能。并且执行速度比
ToArray()

快得多。在处理如此多的数据时,我认为您应该处理流(这当然取决于应用程序)


然后,您就可以编写处理数据的代码,而无需同时将所有数据加载到内存中,您还可以创建一个专门的流类,作为两个流之间的连接。

Yeha。但是应该可以在64位应用程序上使用。。。。。它实际上不需要一个内存日志,只需要一个连续的区域,应该有64位。你能用示例代码支持你的答案吗?你是在磁盘上连接两个文件吗?或者这些字节数组是从哪里填充的?请您用示例代码支持您的答案,对不起,否。这在很大程度上取决于您以后实际想对数据做什么。最有可能的是,你不会仅仅为了好玩而“想要连接两个300兆字节的数据”。你想把它们粘起来,因为你以后想对它们做点什么。例如,您想要将一个巨大的集合写入一个文件。或者,您希望从所有这些值中计算一些值。或者,你想看一部电影,而不是两部电影。等等最后的每一种使用都可能会引导您使用许多其他传递数据的方法,这可能会避免将数据合并到庞大的数组中。例如,如果您希望“将数据作为一个整体传递给某个算法”,您可以尝试使用
IList
而不是
byte[]
并实现
IList
接口,这样它将从两个数组中读取数据,就好像它们是连接在一起的一样。如果要将它们写入文件,只需写入第一个数组,然后将第二个数组附加到同一个文件中(实际上,只需打开file、write-1nd和write-2nd)。等等。对于内存映射文件,它不会帮助您“粘贴数据”。它可以帮助您在内存中“保存非常大的数据块”,而不必一次读取所有数据。这里最重要的是:“数据块”和“不必加载所有数据”。如果你的应用程序创建600meg数组失败,它仍然无法将600meg文件作为一个整体进行memmap,因为它还需要连续的地址空间块。因此,我的回答是误导性的:memmapping不会为您解决任何问题。这会有帮助,但对你来说不是。我会在一段时间后删除这个答案,给你一些时间来阅读评论。只是一个小问题:问题不是
ToArray
。如果您查看它的源代码,您会发现,如果源代码是
ICollection
(a
byte[]
也是
ICollection
),它的行为会有所不同。问题是,
Concat
返回一个
ConcatIterator
对象,然后
ToArray
必须使用通用的
ToArray
方法来实现您描述的效果。@Dirk是的,您是对的
b1.ToArray()
使用
b1.CopyTo
可以正常工作。我已经在我的回答中添加了这个。