.NET的MemoryStream似乎没有.Reset或.Clear方法。
我曾考虑使用以下代码来完成这个操作:
ms.Seek(0, IO.SeekOrigin.Begin)
ms.SetLength(0)
如何正确地清除或重置现有的.NET MemoryStream?
.NET的MemoryStream似乎没有.Reset或.Clear方法。
我曾考虑使用以下代码来完成这个操作:
ms.Seek(0, IO.SeekOrigin.Begin)
ms.SetLength(0)
如何正确地清除或重置现有的.NET MemoryStream?
为什么需要重置内存流?你总是可以创建一个新的。或者你可以使用:
memoryStream.SetLength(0);
memoryStream.SetLength(0)
的目的是什么?我还能再次向流中写入数据吗? - silkfire由于MemoryStream本质上是一个带有索引(以及一些其他支持成员)的字节数组,因此清除字节数组并重置索引可以被认为是重置和清除MemoryStream。如果MemoryStream的初始状态是具有位置零的清零数组,则MemoryStream重置的示例可能如下:
public static void Clear(this MemoryStream source)
{
byte[] buffer = source.GetBuffer();
Array.Clear(buffer, 0, buffer.Length);
source.Position = 0;
source.SetLength(0);
}
错误的说法是MemoryStream.SetLength单独重置或清除MemoryStream,因为如果长度超过当前缓冲区的长度,SetLength只会清除内部缓冲区数组。
重新初始化MemoryStream是一种有效的方法,但不太高效。重新初始化MemoryStream的一个好处是保证流从未关闭。一旦MemoryStream被关闭,就无法再更改它。如果您可以确保MemoryStream实例未关闭,则清除缓冲区可能是一个好方法。
source.GetBuffer()
时,即使是有效的非空流,总是会得到一个异常:_无法访问MemoryStream的内部缓冲区_。更新:在这里解释了原因:https://dev59.com/uHI-5IYBdhLWcg3w18V3#1646219 - Mar我使用了 DotMemory 来对 @Rana_Ian 的解决方案进行性能分析,并调用 GC 强制进行全面的垃圾回收。我发现大型的 Streams 会被卡在 LOH 中!在添加了一行额外代码之后
public static void Clear(MemoryStream ms)
{
var buffer = ms.GetBuffer();
Array.Clear(buffer, 0, buffer.Length);
ms.Position = 0;
ms.SetLength(0);
ms.Capacity = 0; // <<< this one ******
}
Capacity
的实现,然后我发现了以下内容(我稍微简化了一下生成的代码 - 我正在使用Resharper):public virtual int Capacity
{
get
{ .... // some code }
set
{
if ((long) value < this.Length) { // throw some ex }
if (!this._isOpen) { // some another code }
if (!this._expandable && value != this.Capacity) { //MemoryStreamNotExpandable }
if (!this._expandable || value == this._capacity) return;
if (value > 0)
{
byte[] numArray = new byte[value];
if (this._length > 0)
Buffer.InternalBlockCopy((Array) this._buffer, 0, (Array) numArray, 0, this._length);
this._buffer = numArray;
}
else
this._buffer = (byte[]) null; /// <<<< that's it! I need this one
this._capacity = value;
}
}
所以它正在清除缓冲区,我不确定是否正确!
public class ResettableMemoryStream : MemoryStream
{
public void Reset()
{
Seek(0, SeekOrigin.Begin);
}
}
buffer.Reset();
MemoryStream没有重置/清除方法,因为这将是多余的。通过将其设置为零长度,您可以清除它。
当然,您也可以执行以下操作:
memoryStream = new MemoryStream(memoryStream.Capacity());
这将为您产生一个已初始化的相同大小的内存流。
如果您真的想手动清除流,我怀疑您必须通过循环遍历元素来实现。
.SetLength(0)
并保留容量?这是一种滥用内存的行为。 - CodeAngry
SetLength(0)
应该保留Capacity
,而分配一个new MemoryStream()
则应该释放这块内存并分配新的内存。根据使用情况,有些人可能希望保留内存并重置流的Length
和Position
。(无论如何,这就是一个注重内存的 C++ 程序员会考虑的方法)。 - CodeAngry.Capacity
在这些指令之后仍然存在,因此这是避免在不必要时进行 free/alloc 的最佳方法。 - CodeAngry