C# C语言中的流重用#

C# C语言中的流重用#,c#,C#,我一直在玩弄我认为很简单的想法。我希望能够从某处(网站、文件系统、ftp)读入文件,对其执行一些操作(压缩、加密等),然后将其保存到某处(某处可能是文件系统、ftp或其他)。这是一个基本的管道设计。我想做的是读入文件并将其放入MemoryStream,然后对MemoryStream中的数据执行操作,然后将该数据保存在MemoryStream中的某个位置。我想我可以使用相同的流来完成这项工作,但遇到了几个问题: 每次我使用StreamWriter或StreamReader时,我都需要关闭它,这会关

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

  • 每次我使用StreamWriter或StreamReader时,我都需要关闭它,这会关闭流,使我无法再使用它。看来一定有办法解决这个问题
  • 其中一些文件可能很大,因此如果我试图一次读入整个文件,可能会耗尽内存 我希望能够将每个步骤作为单独的线程进行旋转,并在流上有数据时立即开始压缩步骤,然后在流上有一些压缩数据时,我就可以开始保存它(例如)。在C#Streams中,这样的事情很容易实现吗?有人想过如何做到最好吗

    谢谢


    Mike使用助手方法驱动流媒体:

    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);
    
    根据您实际尝试的操作,您会以不同的方式链接流。这也使用了相对较少的内存,因为只有正在操作的数据在内存中。

    StreamReader/StreamWriter不应该被设计为关闭其底层流——这是BCL中一个可怕的错误特性。但它们确实如此,它们不会被更改(因为向后兼容),所以我们不得不面对API的灾难

    但是,如果您想使用StreamReader/Writer,但之后要保持流的打开状态,则有一些行之有效的解决方法

    • 对于StreamReader:不要处理StreamReader。就这么简单。让StreamReader离开而不调用Dispose是无害的。唯一的效果是您的流不会过早关闭,这实际上是一个加号
    • 对于StreamWriter:可能存在缓冲数据,因此您不能让它离开。您必须调用Flush,以确保缓冲数据写入流。然后你就可以让StreamWriter走了。(基本上,你把一个冲水,你通常会把一个处置。)

    除非您正在读取比硬盘更大的数据流,否则我认为您不会耗尽内存:


    但您可能会耗尽地址空间,这正是本文的重点。如果您确实需要使用StreamReader和StreamWriter,但必须确保基础流从不关闭,请创建一个代理流类,该类仅将每个调用传递给基础流,对Close和Dispose方法的调用除外(您可以忽略),并在将基础流传递给读写器构造函数时使用代理将其包装。然后,您可以正常使用读写器类。自.NET 4.0以来,您可以使用内置的
    .CopyTo
    .copytosync
    将流复制到另一个流