如何处理c#流中的位置

时间:2011-01-15 13:48:14

标签: c# stream position memorystream

2 个答案:

答案 0 :(得分:7)

我认为您对文档的期望过高。它确实告诉你一切都做了什么,但它并没有告诉你如何使用它。如果您不熟悉流,只阅读文档将无法提供足够的信息来实际了解如何使用它们。

让我们看一下文档说的内容:

  

“在派生类中重写时,   获取或设置位置   当前流。“

这是“标准文档说”,表示该属性用于跟踪流中的位置,但Stream类本身并未提供实际的实现。实现位于源自Stream类的类中,如FileStreamMemoryStream。每个都有自己的维持位置的系统,因为它们可以对抗完全不同的后端。

甚至可以实现Position属性没有意义的流。您可以使用CanSeek属性来查明流实现是否支持某个职位。

  

“位置属性不保留   跟踪来自的字节数   消耗的流,   跳过,或两者兼而有之。“

这意味着Position属性表示后端实现中的绝对位置,它不仅仅是读取或写入内容的计数器。读取和写入流的方法使用位置来跟踪读取或写入的位置,而不是相反。

对于不支持位置的流实现,它仍然可以返回已读取或写入的字节数,但事实并非如此。 Position属性应反映数据中的实际位置,如果无法执行此操作,则应抛出NotSupportedException异常。

现在,让我们来看看你的情况:

对同一个流使用StreamReaderStreamWriter非常棘手,而且大多没有意义。流只有一个位置,并且将用于读取和写入,因此您必须跟踪两个不同的位置。此外,您必须在每次读取和写入操作后刷新缓冲区,以便缓冲区中没有任何内容,并且当您检索它时,流的Position是最新的。这意味着StreamReaderStreamWriter无法按预期使用,只能作为流的包装。

如果您使用来自不同线程的StreamReaderStreamWriter,则必须同步每个操作。两个线程永远不能同时使用流,因此读/写操作必须执行:

  • 从本地副本设置流的位置
  • 读/写
  • flush buffer
  • 获取流到本地副本的位置
  • 结束锁

流可以用作FIFO缓冲区,但还有其他方法可能更适合您的需求。例如,Queue<T>用作内存FIFO缓冲区。

答案 1 :(得分:5)

  • 这个位置是写作和阅读的“光标”。所以是的,在将Position属性重置为0后,它将开始覆盖现有数据
  • 说实话,首先处理来自多个线程的流时应该小心。目前尚不清楚您是否编写了一个新的Stream子类,或者您是否只是现有流的客户端,但无论哪种方式都需要小心。
  • 目前尚不清楚你的意思是“如果我不处理这个属性” - 这里的“句柄”是什么意思?如果你对你正在做的事情更清楚,那将会有所帮助。

Stream 可能就像一个管道...它真的取决于你正在做什么。目前还不清楚你的意思是“我必须在上次阅读后继续复制数据” - 并且不清楚缓冲区的含义。

如果你能够了解你想要实现的目标,那真的会有所帮助。