c# - 我可以在不写入中间临时存储的情况下获取文件的 GZipStream 吗?

标签 c# 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) 的静态方法。

编辑:完整代码为here如果有用的话。不过,我希望我已在上面的示例中包含了所有相关上下文。

最佳答案

是的,这是可能的,但对于任何标准 .NET 流类来说都不容易。当我需要做这样的事情时,我创建了一个 new type of stream .

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

稍后:这是一个应该接近您所要求的示例。

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

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

关于c# - 我可以在不写入中间临时存储的情况下获取文件的 GZipStream 吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24253975/

相关文章:

c# - 如何将 SQL Server 中存储的 pdf 字节数组显示到图像框中的 asp.net WebForm?

c# - 如何将 GetStringAsync 结果反序列化为翻译文本

c# - 使用 __doPostBack() 进行回发时遇到错误

Android:默认支持 Gzip/Http?

c# - 在加密中丢失特殊的 unicode 字符 (C#)

c# - JSON.NET JObject - 我如何从这个嵌套的 JSON 结构中获取值(value)

c# - 控制台应用程序的数据库上下文

c# - 为什么我的C#gzip生成的文件比Fiddler或PHP大?

c# - gzipstream 内存流到文件

silverlight - HTTP 请求的 Gzip 压缩