【问题标题】:uncompressed file is bigger than original file in GZIP未压缩的文件比 GZIP 中的原始文件大
【发布时间】:2025-10-21 09:10:01
【问题描述】:

我正在使用以下函数进行压缩(感谢http://www.dotnetperls.com/):

public static void CompressStringToFile(string fileName, string value)
    {
        // A.
        // Write string to temporary file.
        string temp = Path.GetTempFileName();
        File.WriteAllText(temp, value);

        // B.
        // Read file into byte array buffer.
        byte[] b;
        using (FileStream f = new FileStream(temp, FileMode.Open))
        {
            b = new byte[f.Length];
            f.Read(b, 0, (int)f.Length);
        }

        // C.
        // Use GZipStream to write compressed bytes to target file.
        using (FileStream f2 = new FileStream(fileName, FileMode.Create))
        using (GZipStream gz = new GZipStream(f2, CompressionMode.Compress, false))
        {
            gz.Write(b, 0, b.Length);
        }
    }

解压:

static byte[] Decompress(byte[] gzip)
    {
        // Create a GZIP stream with decompression mode.
        // ... Then create a buffer and write into while reading from the GZIP stream.
        using (GZipStream stream = new GZipStream(new MemoryStream(gzip), CompressionMode.Decompress))
        {
            const int size = 4096;
            byte[] buffer = new byte[size];
            using (MemoryStream memory = new MemoryStream())
            {
                int count = 0;
                do
                {
                    count = stream.Read(buffer, 0, size);
                    if (count > 0)
                    {
                        memory.Write(buffer, 0, count);
                    }
                }
                while (count > 0);
                return memory.ToArray();
            }
        }
    }

所以我的目标实际上是压缩日志文件,而不是在内存中解压缩它们并将未压缩的文件与原始文件进行比较,以检查压缩是否成功并且我能够成功打开压缩文件。 问题是未压缩的文件大部分时间都比原始文件大,尽管压缩可能成功,但我的比较检查失败了。

知道为什么吗?

顺便说一句,我如何将未压缩文件与原始文件进行比较:

static bool FileEquals(byte[] file1, byte[] file2)
    {
        if (file1.Length == file2.Length)
        {
            for (int i = 0; i < file1.Length; i++)
            {
                if (file1[i] != file2[i])
                {
                    return false;
                }
            }
            return true;
        }
        return false;
    }

【问题讨论】:

  • 字符串有多大?您无法有效地压缩短字符串。压缩器至少需要数千字节才能获得足够的统计信息和匹配的字符串才能很好地压缩。
  • 我正在压缩文件,日志文件,最大为 50 mb
  • CompressStringToFile每个调用的输入平均长度是多少?
  • 目前还不清楚您是如何将压缩的原始 string 转换为传递给 FileEquals() 的 byte[] 的。编码事故很常见。

标签: c# .net compression gzip


【解决方案1】:

试试这个方法来压缩一个文件:

public static byte[] Compress(byte[] raw)
{
using (MemoryStream memory = new MemoryStream())
{
    using (GZipStream gzip = new GZipStream(memory,
    CompressionMode.Compress, true))
    {
    gzip.Write(raw, 0, raw.Length);
    }
    return memory.ToArray();
   }
  }
}

还有这个解压:

 static byte[] Decompress(byte[] gzip)
{
// Create a GZIP stream with decompression mode.
// ... Then create a buffer and write into while reading from the GZIP stream.
using (GZipStream stream = new GZipStream(new MemoryStream(gzip), CompressionMode.Decompress))
{
    const int size = 4096;
    byte[] buffer = new byte[size];
    using (MemoryStream memory = new MemoryStream())
    {
    int count = 0;
    do
    {
        count = stream.Read(buffer, 0, size);
        if (count > 0)
        {
        memory.Write(buffer, 0, count);
        }
    }
    while (count > 0);
    return memory.ToArray();
    }
}
}

}

告诉我它是否有效。

祝你好运。

【讨论】:

  • 感谢我刚刚测试过它——它可以工作,但目前只在内存中,所以我还没有使用文件流,它应该也可以工作,不是吗?我做错了什么?
  • 我想我理解了我的问题,我在调用压缩函数之前这样做了: private static void ZIP(string source_file) { string fileToZIP = File.ReadAllText(source_file); CompressStringToFile(source_file + ".gz", fileToZIP); } 所以它是因为转换为字符串 File.ReadAllText(source_file)
  • @MoshMosh 是的,我也认为您的代码中的错误。我很高兴它现在对你有用:)
【解决方案2】:

认为使用最简单的 API 调用会更好,试试Stream.CopyTo()。我在您的代码中找不到错误。如果我正在处理它,我可能会确保所有内容都正确刷新..不记得 GZipStream 是否会在 using 块关闭时将其输出刷新到 FileStream.. 但是你也说最后文件更大,而不是更小。

无论如何,根据我的经验,最好的策略.. 不要在不需要时重写容易遇到问题的代码。至少你测试过它;)

【讨论】: