62

.NET MemoryStream 似乎没有 .Reset 或 .Clear 方法。

我正在考虑使用以下代码来完成此操作:

ms.Seek(0, IO.SeekOrigin.Begin)
ms.SetLength(0)

清除或重置现有 .NET MemoryStream 的正确方法是什么?

4

4 回答 4

92

为什么需要重置内存流?你总是可以创建一个新的。或者您可以使用:

memoryStream.SetLength(0);
于 2010-03-17T13:13:58.503 回答
30

由于 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 实例没有关闭,那么清除缓冲区可能是要走的路。

于 2012-03-31T17:33:15.717 回答
1

我使用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 ******
}

我点击F12来查看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;
  }
}

所以它正在清除缓冲区,我不确定这是否正确!

于 2020-10-13T13:58:58.417 回答
-2

内存流没有重置/清除方法,因为它是多余的。通过将其设置为零长度可以清除它。

当然,您总是可以这样做:

memoryStream = new MemoryStream(memoryStream.Capacity());

这将为您产生一个与初始化大小相同的内存流。

如果您真的想手动清除流,我怀疑您将不得不求助于遍历元素。

于 2010-03-17T13:59:26.193 回答