崩溃安全的飞行压缩与GZipStream

本文关键字:GZipStream 压缩 飞行 安全 崩溃 | 更新日期: 2023-09-27 18:06:10

当数据写入时,我正在压缩日志文件,类似于:

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并不是必须的,如果有其他东西可以给我们想要的结果

崩溃安全的飞行压缩与GZipStream

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

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

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

因此,即使您的流写在任意点被中断,大多数流仍然是好的。你可以自己编写一个小工具,从它读取并在它看到的第一个异常时停止。

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

是的,但这不仅仅是冲洗。看看zlib发行版中的gzlog.h和gzlog.c。它完全可以满足您的需求,有效地将短日志条目添加到gzip文件中,并始终留下有效的gzip文件。它还具有防止在过程中崩溃或关闭的保护,仍然会留下一个有效的gzip文件,并且不会丢失任何日志条目。

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