【问题标题】:GZipStream compression not workingGZipStream 压缩不起作用
【发布时间】:2013-12-06 12:06:40
【问题描述】:

我正在尝试读取文件并使用 GZipStream 对其进行压缩,如下所示:

using (var outStream = new MemoryStream())
{
    using (var fileStream = new FileStream(filename, FileMode.Open, FileAccess.Read))
    {
        using (var gzipStream = new GZipStream(outStream, CompressionMode.Compress))
        {
            fileStream.CopyTo(gzipStream);

            Debug.WriteLine(
                "Compressed from {0} to {1} bytes", 
                fileStream.Length, 
                outStream.Length);

            // "outStream" is utilised here (persisted to a NoSql database).
        }
    }
} 

问题是outStream.Length 总是显示 10 个字节。我做错了什么?

我尝试在fileStream.CopyTo 行之后调用gzipStream.Close()(如其他论坛中所建议的那样),但这似乎也关闭了outStream,因此使用它的后续代码会失败。

【问题讨论】:

  • 根据 [the msdn][1] 没有理由过于信任 Stream.length 属性,它可能会或可能不会实现。您是否通过其他方式检查获得的外流不正确? [1]:msdn.microsoft.com/en-us/library/…

标签: c# gzipstream


【解决方案1】:

MSDN 说:The write operation might not occur immediately but is buffered until the buffer size is reached or until the Flush or Close method is called.

换句话说,所有写操作都完成并不意味着数据已经在MemoryStream 中。您必须先执行gzipStream.Flush() 或关闭 gzipStream。

例子:

using (var outStream = new MemoryStream())
{
    using (var fileStream = new FileStream(filename, FileMode.Open, FileAccess.Read))
    {
        using (var gzipStream = new GZipStream(outStream, CompressionMode.Compress))
        {
            fileStream.CopyTo(gzipStream);
        }

        Debug.WriteLine(
                "Compressed from {0} to {1} bytes", 
                fileStream.Length, 
                outStream.Length);

        // "outStream" is utilised here (persisted to a NoSql database).
    }
} 

此外,理想情况下,也将其放在 FileStream 之外 - 您希望尽快关闭文件,而不是等待其他处理完成。

【讨论】:

  • 一开始我怀疑缺乏刷新是罪魁祸首,但docs on GZipStream.Flush 明确指出“此方法的当前实现没有功能”,关闭流确实是唯一的选择。
  • @O.R.Mapper:ILSpy 似乎证实了这一点。哇,这有点过分了。我猜他们没有办法实现它,因为它不能增量工作,你可能需要一次压缩和写入所有数据。
  • 那行不通 - 在 fileStream.CopyTo() 周围使用 using (或者实际上在 CopyTo 之后关闭 gzipStream,如我的问题中所述)导致 outStream 也关闭,使其在后面的行中无法使用.
  • @AndrewStephens:是的,这就是 GZipStream 构造函数的第三个参数的用途——如果你使用new GZipStream(outStream, CompressionMode.Compress, true),它应该让 outStream 保持打开状态。不要忘记倒带MemoryStream (outStream.Position = 0;)。
  • 第三个参数成功了,谢谢!标记为已回答。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多