我是否可以在不写入中间临时存储的情况下获取文件的GZipStream?

我是否可以为磁盘上的文件获取GZipStream而无需将整个压缩内容写入临时存储? 我目前正在磁盘上使用临时文件,以避免在非常大的文件上使用MemoryStream可能导致内存耗尽(这很好)。

  public void UploadFile(string filename) { using (var temporaryFileStream = File.Open("tempfile.tmp", FileMode.CreateNew, FileAccess.ReadWrite)) { using (var fileStream = File.OpenRead(filename)) using (var compressedStream = new GZipStream(temporaryFileStream, CompressionMode.Compress, true)) { fileStream.CopyTo(compressedStream); } temporaryFileStream.Position = 0; Uploader.Upload(temporaryFileStream); } } 

我想做的是通过创建GZipStream来消除临时存储,并且只有当Uploader类从它请求字节时才从原始文件中读取它。 这样的事情可能吗? 如何构建这样的实现?

请注意, Upload是一个静态方法,带有签名static void Upload(Stream stream)

编辑:完整的代码在这里,如果它是有用的。 我希望我已经在上面的示例中包含了所有相关的上下文。

是的,这是可能的,但不容易使用任何标准的.NET流类。 当我需要做这样的事情时,我创建了一种新类型的流 。

它基本上是一个循环缓冲区,允许一个生产者(作家)和一个消费者(读者)。 它很容易使用。 让我举一个例子。 在此期间,您可以调整文章中的示例。

后来:这是一个应该接近你要求的例子。

 using (var pcStream = new ProducerConsumerStream(BufferSize)) { // start upload in a thread var uploadThread = new Thread(UploadThreadProc(pcStream)); uploadThread.Start(); // Open the input file and attach the gzip stream to the pcStream using (var inputFile = File.OpenRead("inputFilename")) { // create gzip stream using (var gz = new GZipStream(pcStream, CompressionMode.Compress, true)) { var bytesRead = 0; var buff = new byte[65536]; // 64K buffer while ((bytesRead = inputFile.Read(buff, 0, buff.Length)) != 0) { gz.Write(buff, 0, bytesRead); } } } // The entire file has been compressed and copied to the buffer. // Mark the stream as "input complete". pcStream.CompleteAdding(); // wait for the upload thread to complete. uploadThread.Join(); // It's very important that you don't close the pcStream before // the uploader is done! } 

上传线程应该非常简单:

 void UploadThreadProc(object state) { var pcStream = (ProducerConsumerStream)state; Uploader.Upload(pcStream); } 

当然,您可以将生产者放在后台线程上,并在主线程上完成上传。 或者将它们都放在后台线程上。 我不熟悉你的上传者的语义,所以我会把这个决定留给你。