使用GZipStream进行崩溃安全的即时压缩

时间:2013-03-27 11:20:58

标签: c# .net stream compression gzipstream

我在写入数据时压缩日志文件,如:

using (var fs = new FileStream("Test.gz", FileMode.Create, FileAccess.Write, FileShare.None))
{
  using (var compress = new GZipStream(fs, CompressionMode.Compress))
  {
    for (int i = 0; i < 1000000; i++)
    {
      // Clearly this isn't what is happening in production, just 
      // a simply example
      byte[] message = RandomBytes();
      compress.Write(message, 0, message.Length);

      // Flush to disk (in production we will do this every x lines, 
      // or x milliseconds, whichever comes first)
      if (i % 20 == 0)
      {
        compress.Flush();
      }
    }
  }
}

我想要确保的是,如果进程崩溃或被杀死,存档仍然有效且可读。我曾经希望自上次同花以来的任何事情都是安全的,但我最终只是以一个腐败的档案结束。

有没有什么方法可以确保我在每次刷新后最终得到一个可读的存档?

注意:我们使用GZipStream并不是必需的,如果其他东西能给我们所需的结果。

3 个答案:

答案 0 :(得分:2)

一个选项是让Windows处理压缩。只需在存储日志文件的文件夹上启用压缩。复制压缩文件时应该注意一些performance considerations,我不知道NT压缩与GZipStream或其他压缩选项的比较有多好。您可能希望比较压缩率和CPU负载。

如果您不想在整个文件夹上启用压缩,还可以选择打开压缩文件。我没试过这个,但你可能想看一下:http://social.msdn.microsoft.com/forums/en-US/netfxbcl/thread/1b63b4a4-b197-4286-8f3f-af2498e3afe5

答案 1 :(得分:1)

好消息:GZip是一种流媒体格式。因此,流末尾的损坏不会影响已经写入的开头。

因此,即使您的流式写入在任意点中断,大部分流仍然是好的。你可以自己写一个从它上面读取的小工具,并在它看到的第一个例外时停止。

如果你想要一个没有错误的解决方案,我建议每隔x秒将日志分成一个文件(可能是x = 1或10?)。写入扩展名为“.gz.tmp”的文件,并在文件完全写入并关闭后重命名为“.gz”。

答案 2 :(得分:0)

是的,但它涉及的不仅仅是冲洗。请查看gzlog.h发布中的gzlog.czlib。它完全符合您的要求,有效地将短日志条目添加到gzip文件中,并始终保留有效的gzip文件。它还具有防止在此过程中崩溃或关闭的保护,仍然保留有效的gzip文件,并且不会丢失任何日志条目。

我建议不要使用GZIPStream。这是错误的,并没有提供必要的功能。请使用DotNetZip作为zlib的接口。