【问题标题】:How to use DeflateStream on multiple chunks of data?如何在多块数据上使用 DeflateStream?
【发布时间】:2014-09-01 01:02:20
【问题描述】:

我使用DeflateStream 实现了 Websocket 压缩,如下所示:

    public byte[] Compress(Stream input)
    {
        using (var compressStream = new MemoryStream())
        using (var compressor = new DeflateStream(compressStream, CompressionMode.Compress))
        {
            input.CopyTo(compressor);
            compressor.Close();

            return compressStream.ToArray();
        }
    }

这适用于第一条消息,但是我需要保持相同的压缩上下文(LZ77 滑动窗口)并将其重新用于第二条消息,而不是每次都从新字典开始。

我目前的解决方法是设置 Websockets client_no_context_takeoverserver_no_context_takeover 选项,让对方知道我们没有回收放气状态。

那么我怎样才能更改上面的代码,以便为下一次调用保留放气“状态”?

【问题讨论】:

  • 您能否在内存流仍在压缩器中打开时从内存流中读取,而不是将其转换为数组?
  • @speising 我想是的。但是在您调用 Close() 之前,压缩器不会将任何内容刷新到内存流中。
  • 这是一个微优化,违背了当前所有向 WebSockets 添加压缩的提议。所有坏主意之母。
  • @HansPassant Chrome 预计“permessage-deflate”默认使用这种压缩,我只是想遵循他们的标准。

标签: c# compression gzip zlib deflate


【解决方案1】:

您的代码已经实现了“使用”,它会在方法返回时处理所有对象。因此,您无法在不同调用之间保持“状态”。

尝试在方法之外维护对 compressorcompressStream 的引用。

【讨论】:

  • 我知道,但这在这种情况下无济于事,因为您必须在 DeflateStream 上调用 Close() 才能读取结果,因此在类级别保持引用似乎毫无意义。
【解决方案2】:

您实际上可以在不关闭压缩器的情况下读取MemoryStream

input.CopyTo(compressor);
compressStream.Position = 0;
var mem2 = new BinaryReader(compressStream);
mem2.Read(buf, 0, 10000000);

将产生compressStream 的内容。下次写之前注意定位到最后! (当然,你必须让你的对象保持活力,如前所述)。

【讨论】:

  • 不是这样吗?我已经尝试过这段代码,但在关闭压缩器之前,compressStream 中没有可用的字节?
猜你喜欢
  • 2010-10-20
  • 1970-01-01
  • 1970-01-01
  • 2013-09-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-01-19
  • 2021-11-29
相关资源
最近更新 更多