C# 中的 MemoryStream 和字节数组比较

70
我有一个生成并返回MemoryStream的函数。生成完成后,MemoryStream的大小是固定的,我不需要再向其中写入任何内容,只需要输出即可,比如将其写入到MailAttachment或者数据库中。
那么,传递这个对象的最佳方式是什么?使用MemoryStream还是Byte Array?如果我使用MemoryStream,读取后需要重置位置。
建议使用byte数组来传递该对象。因为MemoryStream会占用更多内存,并且在传递时需要重置位置,操作较为繁琐。而byte数组则更加轻便和易于传递。

你需要多频繁地重新阅读数据? - Oded
这要看情况。有时只需要一次,有时需要2-3次。 - LuckyStrike
如果您传递了一个 Byte 数组,那么您是否每次使用它都要创建一个新的 MemoryStream - Dan Puzey
目前我使用MemoryStream。我有一个包装器围绕着MemoryStream和一个将MemoryStream转换为字节数组的方法。 - LuckyStrike
结果有多大?这是最重要的事情。 - H H
好的,这意味着您不必担心碎片化问题。 - H H
3个回答

82

如果必须将所有数据存储在内存中,那么从很多方面来看,选择是任意的。如果您有现有的代码操作Stream,则MemoryStream可能更方便,但如果您返回byte[],则始终可以将其包装在new MemoryStream(blob)中。

这也可能取决于它的大小和保留时间; MemoryStream可以超过规定大小,这既有优点也有缺点。如果您要保留数据一段时间,则将其强制转换为byte[]可能很有用,因为它会修剪掉任何超额部分;但是,如果您仅短暂保留它,则可能会适得其反,因为在创建新副本时,它将强制您重复大多数(至少:一半)数据。

所以; 它主要取决于上下文、用法和目的。在大多数情况下,“任何可行并且清晰简单”的方法都可以满足要求。如果数据特别大或保留时间较长,则可能需要刻意微调。

byte[]方法的另一个优点:如果需要,多个线程可以同时安全地访问它(只要它们正在读取)-这对于MemoryStream不成立。但是,这可能是一种虚假的优点:大多数代码不需要从多个线程访问byte[]


4
有趣的是,MemoryStream 无论如何都会内部使用 byte[],所以问题更多地涉及到需要什么样的API - 是 Stream 还是字节数组。 - Adam Houldsworth
2
@Adam 确切地说,超大的内部 byte[] 可以通过 GetBuffer() 获得,但是你需要非常小心,不要查看超出范围的字节,因为它们是纯垃圾。 - Marc Gravell
线程安全是提出这个问题的主要原因。另一个原因是我的代码使用字节数组作为参数。 - LuckyStrike
如果你想避免额外的复制,那么最好只需通过 ms.ToArray() 返回 byte[],或者如果你真的非常想要避免额外的复制,可以使用 new ArraySegment<byte>(ms.GetBuffer(), 0, (int)ms.Length) - Marc Gravell
ArraySegment 可能不兼容(作为参数),ToArray 运行风险碎片化。 - H H
@HenkHolterman 是的,但为了避免碎片化,您必须使用 GetBuffer(),如果缓冲区不是100%满(几乎所有情况),则必须使用类似于 ArraySegment<byte> 的东西 - 也许是 byte[] 加上 int length - Marc Gravell

9

MemoryStream类用于向流中添加元素。

存在文件指针,模拟随机访问,取决于其实现方式。因此,MemoryStream不适用于任何时刻访问任何项。

byte数组允许在未分配之前的任何时刻随机访问任何元素。

与byte []相邻的是MemoryStream,它保存在内存中(取决于类名)。然后最大分配大小为4 GB。

如果需要以任何索引号访问数据,请使用byte []。否则,当您只有字符串时,MemoryStream被设计为与其他要求流作为输入的东西一起使用。


1
使用byte[]是因为它是一个固定大小的对象,这使得内存分配和清理更容易,并且几乎没有开销 - 特别是因为您不需要使用MemoryStream的函数。此外,您希望尽快处理该流,以便它可以释放可能正在使用的非托管资源。

6
一个 MemoryStream 没有需要释放的非托管资源。强制将其转换为 byte[] 可能会因为重复而占用更多内存。我的观点是:情况并不那么简单。 - Marc Gravell

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接