Assume I have copied a byte buffer into a memory stream using this
memoryStream.Read(data, 0, data.Length);
有没有办法清空流并重用它来读取其他数据?
我想避免创建许多MemoryStream对象,而是更喜欢使用一个实例,在使用之间重置它。
Assume I have copied a byte buffer into a memory stream using this
memoryStream.Read(data, 0, data.Length);
有没有办法清空流并重用它来读取其他数据?
我想避免创建许多MemoryStream对象,而是更喜欢使用一个实例,在使用之间重置它。
您可以通过将流的位置(Position)设置为0且长度(Length)设置为0来重复使用MemoryStream。
MemoryStream ms = new MemoryStream();
// Do some stuff with the stream
// Reset the stream so you can re-use it
ms.Position = 0; // Not actually needed, SetLength(0) will reset the Position anyway
ms.SetLength(0);
// Do some more stuff with the stream
将长度设置为0并不会清除现有缓冲区,它只会重置内部计数器。因此,现有的缓冲区分配保持不变,但所有关于缓冲区使用量的记录都被重置,这样您就可以重新使用它。
更新:我刚刚快速查看了SetLength的代码实现,如果将长度设置为0,则Position属性会自动重置为0,因此您甚至不需要显式设置Position属性,仅重置长度即可。
您可以将Position
设置为0,这将有效地重置流。
然而,正如此答案所示,重用内存流不太可能带来任何性能优势。更好的方法是创建更多的内存流,这样更为经济。
另一种选择是使用固定的byte[]
作为重复使用的缓冲区。
如果您使用memoryStream.getBuffer()
和偏移量/长度(使用memoryStream.Position
和memoryStream.Length
检测边界)直接访问byte[]
数据,Reader
/Writer
/BinaryFormatter
类或其他接受Stream
的类,用于将原始/复杂类型读入/写入缓冲区(这就是MemoryStream
的作用),您可以避免无用的复制操作,因为MemoryStream
已经基于字节数组。
我在异步发送/接收套接字操作中以这种方式使用它来接受byte[]
,但请注意-如果您在超出当前Length
的缓冲区中写入了一些内容,并希望通过SetLength()
增加其长度以便使用Reader类进行读取-您会得到非常不方便的行为(在我看来)-如果长度增加,此方法会将旧长度和新长度之间的每个字节都置零。
我通过修改MemoryStream
的源代码(在SetLength()
中调用了一个Array.Clear,并添加了一些管理.NET内部类的内容)来解决这个问题,并在我的项目中使用它。
关于重用MemoryStream,我同意Chris Taylor的回答(SetLength(0)
)
memoryStream.Seek(0, SeekOrigin.Begin);
Position
只设置读写位置,但保持数据流中数据的长度不变。所以,后续的读操作会再次给你已经写入到数据流中的数据。使用SetLength(0)
重置二者。链接中的答案也是错误的。 SetLength(0) 确实重置了长度和位置,并且保留了缓冲区。 - Holger Böhnke