重置或清除 .NET MemoryStream

发布于 2024-08-25 15:44:40 字数 194 浏览 9 评论 0原文

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

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

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

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

The .NET MemoryStream does not appear to have a .Reset or .Clear method.

I was thinking of using the following code to accomplish this:

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

What is the proper way to clear or reset an existing .NET MemoryStream?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

独守阴晴ぅ圆缺 2024-09-01 15:44:40

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

memoryStream.SetLength(0);

Why do you need resetting memory stream? You always can create a new one. Or you can use:

memoryStream.SetLength(0);
儭儭莪哋寶赑 2024-09-01 15:44:40

由于 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 实例未关闭,那么清除缓冲区可能是可行的方法。

Since a MemoryStream is essentially a byte array with an index (and some other supporting members) clearing the byte array and resetting the index can be considered resetting and clearing the MemoryStream. If the initial state of a MemoryStream is a zeroed array with a position of zero then an example of a MemoryStream reset may be:

public static void Clear(this MemoryStream source)
{
  byte[] buffer = source.GetBuffer();
  Array.Clear(buffer, 0, buffer.Length);
  source.Position = 0;
  source.SetLength(0);
}

It is incorrect to say that MemoryStream.SetLength alone resets or clears the MemoryStream since SetLength only clears the internal buffer array if the length exceeds the current buffer's length.

Reinitializing a MemoryStream is a valid approach but less efficient. One benefit of reinitializing the MemoryStream would be to guarantee that the stream was never closed. Once the MemoryStream is closed it can no longer be changed. If you can ensure that the MemoryStream instance isn't closed then clearing the buffer may be the way to go.

与他有关 2024-09-01 15:44:40

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

这一点(我稍微简化了生成的代码 - 我正在使用 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;
  }
}

我单击 F12 查看 Capacity 实现,我发现了 它正在清除缓冲区,我不确定这是否正确!

I used DotMemory to Profile @Rana_Ian solution, and I called GC to enforce full collection.
I found that large Streams will stuck in LOH!
And after adding one extra line

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 ******
}

I clicked on F12 to see Capacity Implementation, And I found this (I simplified generated code a little bit - I'm using 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;
  }
}

So It's clearing the Buffer, I'm not sure if this is correct or not!

清醇 2024-09-01 15:44:40

您可以像这样创建内存流:

public class ResettableMemoryStream : MemoryStream
{
    public void Reset()
{
    Seek(0, SeekOrigin.Begin);
}
}  

在代码调用中进行操作后:

 buffer.Reset();

you can create your memorystream like this:

public class ResettableMemoryStream : MemoryStream
{
    public void Reset()
{
    Seek(0, SeekOrigin.Begin);
}
}  

and after your operation in your code call:

 buffer.Reset();
不语却知心 2024-09-01 15:44:40

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

当然你总是可以这样做:

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

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

如果您确实想手动清除流,我怀疑您将不得不诉诸循环元素。

The memorystream does not have a reset/clear method because it would be redundant. By setting it to zero length you clear it.

Of course you could always do:

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

This would yield you a memorystream of the same size that is initialized.

If you really want to manually clear the stream I suspect you would have to resort to looping through the elements.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文