我可以得到一个GZipStream文件不写入中间临时存储

本文关键字:中间 存储 文件 GZipStream 一个 我可以 | 更新日期: 2023-09-27 18:08:49

我可以在不将整个压缩内容写入临时存储的情况下获得磁盘上文件的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)

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

我可以得到一个GZipStream文件不写入中间临时存储

是的,这是可能的,但是对于任何标准的。net流类来说都不容易。当我需要做这样的事情时,我创建了一种新的流类型。

它基本上是一个循环缓冲区,允许一个生产者(写入者)和一个消费者(读取者)。它很容易使用。让我举个例子。同时,您可以改编本文中的示例。

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

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);
}

当然,你可以将制作人放在后台线程中,并在主线程中完成上传。或者把它们都放在后台线程上。我不熟悉你的上传器的语义,所以我把这个问题留给你。