C#中的流重用

时间:2009-06-10 03:54:15

标签: c#

我一直在玩我认为简单的想法。我希望能够从某个地方(网站,文件系统,ftp)读取文件,对其执行一些操作(压缩,加密等),然后将其保存在某个地方(某处可能是文件系统,ftp或其他) 。这是一个基本的管道设计。我想要做的是读入文件并将其放入MemoryStream,然后对MemoryStream中的数据执行操作,然后将该数据保存在MemoryStream中的某处。我以为我可以使用相同的Stream来做到这一点,但遇到了几个问题:

  1. 每次我使用StreamWriter或StreamReader时,我都需要关闭它并关闭流,以便我不再使用它。这似乎必须有某种方法来解决这个问题。
  2. 其中一些文件可能很大,所以如果我尝试一次读完整个内容,我可能会耗尽内存。
  3. 我希望能够将每个步骤作为单独的线程启动,并在流上有数据时立即开始压缩步骤,然后一旦压缩在流上有一些压缩数据我可以开始保存它(例如)。使用C#Streams可以轻松实现这一切吗?有人想过如何做到最好吗?

    谢谢,

    麦克

3 个答案:

答案 0 :(得分:4)

使用辅助方法驱动流媒体:

static public void StreamCopy(Stream source, Stream target)
{
    byte[] buffer = new byte[8 * 1024];

    int size;
    do
    {
      size = source.Read(buffer, 0, 8 * 1024);
      target.Write(buffer, 0, size);
    } while (size > 0);
}

您可以轻松组合您需要的任何内容:

using (FileStream iFile = new FileStream(...))
using (FileStream oFile = new FileStream(...))
using (DeflateStream oZip = new DeflateStream(outFile, CompressionMode.Compress))
    StreamCopy(iFile, oZip);

根据您实际要做的事情,您将以不同方式链接流。这也使用相对较少的内存,因为只有正在操作的数据才在内存中。

答案 1 :(得分:1)

StreamReader / StreamWriter 不应该设计为关闭他们的基础流 - 这是BCL中的一个可怕的错误。但他们这样做,他们不会被改变(因为向后兼容),所以我们一直坚持这个API的灾难。

但是如果您想使用StreamReader / Writer但是之后保持Stream打开,那么有一些完善的解决方法。

  • 对于StreamReader:请勿处置StreamReader。就这么简单。让StreamReader没有调用Dispose是无害的。唯一的影响是你的Stream不会过早关闭,这实际上是一个加号。
  • 对于StreamWriter:可能存在缓冲数据,因此您无法放弃它。您必须调用Flush,以确保缓冲的数据被写入Stream。 然后你可以让StreamWriter去。 (基本上,你把一个Flush放在你通常放置Dispose的地方。)

答案 2 :(得分:0)

除非您正在阅读比您的硬盘更大的流,否则我认为您的内存不会用完:

http://blogs.msdn.com/ericlippert/archive/2009/06/08/out-of-memory-does-not-refer-to-physical-memory.aspx