0

我正在压缩一个日志文件,因为数据被写入其中,例如:

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,如果其他东西会给我们想要的结果。

4

3 回答 3

2

一种选择是让 Windows 处理压缩。只需在存储日志文件的文件夹上启用压缩。在复制压缩文件时,您应该注意一些性能注意事项,我不知道 NT 压缩与GZipStream其他压缩选项相比的性能如何。您可能想要比较压缩率和 CPU 负载。

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

于 2013-03-27T14:19:49.540 回答
1

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

我建议不要使用 GZIPStream。它有问题,不提供必要的功能。改用DotNetZip作为 zlib 的接口。

于 2013-03-27T14:56:36.803 回答
1

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

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

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

于 2013-03-27T13:32:31.110 回答