为什么在 C# 中使用 SharpZipLib 时,压缩后字符串的 GZip 压缩大小大于原始大小

Why am I getting GZip compression size of a string more than the original size after compression when using SharpZipLib in C#

我的字符串是一个 Json 文件 (test.json),其内容如下

{
  "objectId": "bbad4cc8-bce8-438e-8683-3e603d746dee",
  "timestamp": "2021-04-28T14:02:42.247Z",
  "variable": "temperatureArray",
  "model": "abc.abcdefg.abcdef",
  "quality": 5,
  "value": [ 43.471600438222104, 10.00940101687303, 39.925500606152, 32.34369812176735, 33.07786476010357 ]
}

我压缩如下

using ICSharpCode.SharpZipLib.GZip;
using System;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Text;

namespace GZipTest
{
    public static class SharpZipLibCompression
    {
        public static void Test()
        {
            Trace.WriteLine("****************SharpZipLib Test*****************************");
            var testFile = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "test.json");
            var text = File.ReadAllText(testFile);
            var ipStringSize = System.Text.UTF8Encoding.Unicode.GetByteCount(text);
            var compressedString = CompressString(text);
            var opStringSize = System.Text.UTF8Encoding.Unicode.GetByteCount(compressedString);
            float stringCompressionRatio = (float)opStringSize / ipStringSize;
            Trace.WriteLine("String Compression Ratio using SharpZipLib" + stringCompressionRatio);
        }

        public static string CompressString(string text)
        {
            if (string.IsNullOrEmpty(text))
                return null;
            byte[] buffer = Encoding.UTF8.GetBytes(text);
            using (var compressedStream = new MemoryStream())
            {
                GZip.Compress(new MemoryStream(buffer), compressedStream, false);
                byte[] compressedData = compressedStream.ToArray();
                return Convert.ToBase64String(compressedData);
            }
        }
    }
}

但是我的压缩字符串大小(opStringSize)大于原始字符串大小(ipStringSize)。为什么?

您的基准测试有一些相当基本的问题:

  1. 您在计算长度时使用 UTF-16 将输入字符串编码为字节(UTF8Encoding.Unicode 只是一种不明确的写法 Encoding.Unicode,即 UTF-16)。每个字符编码为 2 个字节,但这些字节中的大部分将为 0。
  2. 您正在对输出进行 base64 编码。虽然这是一种将任意二进制数据打印为文本的方法,但它使用 4 个字符来表示 3 个字节的数据,因此您将输出的大小增加了 33%。
  3. 然后您将再次使用 UTF-16 将 base64 编码的字符串转换为字节,每个字符再次占用 2 个字节。所以这是一个人为的 2x 添加到你的结果...

碰巧 UTF-16 的两种用途或多或少抵消了,但 base64 编码位仍然是造成您所看到的许多差异的原因。

把它拿出来,你得到的压缩比是:0.80338985。

考虑到压缩会带来开销,这还不错:有些数据始终需要出现在 GZip 流中,而且无论您的数据压缩得有多好,它都会存在。您只能真正期望压缩对较大的输入产生任何显着差异。

See here.