【问题标题】:Where are the parameters for Indy's TIdCompressorZLib.CompressStream Method documented?Indy 的 TIdCompressorZLib.CompressStream 方法的参数记录在哪里?
【发布时间】:2013-10-11 17:45:13
【问题描述】:

TIdComproessorZLib 组件用于 Delphi/C++ Builder Indy 库中的压缩和解压。 CompressStream 方法的定义如下:

public: virtual __fastcall CompressStream(TStream AInStream, TStream AOutStream, const TIdCompressionLevel ALevel, const int AWindowBits, const int AMemLevel, const int AStrategy);

帮助文件中这些参数的完整描述是:

CompressStream 是一个公共的重写过程。实现了 抽象祖先类中声明的虚方法。

AInStream 是包含未压缩内容的流 压缩操作。

AOutStream 是用于存储压缩内容的流 压缩操作。 AOutStream 在输出之前被清除 操作中的压缩内容。当 AOutStream 是 省略,AInStream 中的流被清除并重用于输出 从压缩操作。

使用 ALevel 指示所需的压缩级别 手术。

使用 AWindowsBits 和 AMemLevel 控制内存占用 需要使用 ZLib 库执行内存压缩。

使用 AStrategy 来控制在 压缩操作。

在 TIdCompressionLevel 的帮助页面上定义了 ALevel 的值,但我找不到任何指示应该为 AWindowBits、AMemLevel 或 AStrategy 使用哪些值,它们只是整数。

我查看了源代码,但 CompressStream 只是委托给 IndyCompressStream,它在帮助文件中列为:

IndyCompressStream(TStream InStream, TStream OutStream, const int level = Z_DEFAULT_COMPRESSION, const int WinBits = MAX_WBITS, const int MemLevel = MAX_MEM_LEVEL, const int Stratagy = Z_DEFAULT_STRATEGY);

IndyCompressStream 的帮助甚至没有列出 CompressStream 所做参数的最少描述。

我找到了(我认为)IndyCompressStream 中提到的那些默认常量的文件,source\Indy10\Protocols\IdZLibHeaders.pas,它们是

  Z_DEFAULT_STRATEGY    = 0;
  Z_DEFAULT_COMPRESSION  = -1;
  MAX_WBITS = 15; { 32K LZ77 window }
  MAX_MEM_LEVEL = 9;

但是,根据TIdCompressionLevel 的文档,Z_DEFAULT_COMPRESSION 的值甚至不是该参数的合法值

是否有一些文档说明 AWindowBits、AMemLevel 和 AStrategy 对这个组件的意义,以及对它们使用哪些值是合理的?上面列出的值是实际推荐的默认值吗?此外,源文件包括“indy”、“Indy10”和“indyimpl”目录。我们应该使用哪些来查找当前 Indy 组件的来源?

谢谢!

【问题讨论】:

  • 现在这就是提问的方式。干得好。
  • 希望用它做什么?
  • Indy 有文档吗?
  • @DavidHeffernan:Indy has documentation,不过好久没更新了。
  • @RemyLebeau:有什么方法可以帮助我们更新文档吗?

标签: delphi c++builder indy zlib


【解决方案1】:

您需要查看zlib.h 中的 zlib 文档。特别是parameters to deflateInit2()

在几乎所有情况下,您唯一应该处理的就是压缩级别和窗口位。对于窗口位,您通常会将窗口大小保留为 32K (15),但为 gzip 格式 (31) 添加 16,或取反 (-15) 以获得没有标题或尾部的原始 deflate 格式。对于某些特殊类型的数据,您可能会通过不同的压缩策略得到改进,例如图像或其他数字数据数组。

【讨论】:

  • 没有什么比让 zlib 的作者之一来回答我的问题更棒了!谢谢!我确实需要更改的一件事是我正在尝试创建 gzip 格式,因为这是我的服务器所期望的,并且需要将 16 添加到 windowBits,如您为 deflateInit2() 提供的 zlib 参考中所述。
  • 啊,是的,通常那个也被搞砸了。我会修复答案。
【解决方案2】:

感谢 cmets 和答案,尤其是 Remy 和 Mark。我没有意识到 Indy 单元是 zlib 的包装器,并且参数是在 zlib 库中定义的。

我正在尝试创建一个 gzip 格式的流,以便上传到需要 gzip 的服务器。

这里是gzip压缩和解压的工作代码:

void __fastcall TForm1::Button1Click(TObject *Sender)
{
TStringStream* streamIn = new TStringStream(String("This is some data to compress"));
TMemoryStream* streamCompressed = new TMemoryStream;
TStringStream* streamOut = new TStringStream;

/* this also works to compress to gzip format, but you must #include <IdZlib.hpp>
CompressStreamEx(streamIn, streamCompressed, Idzlib::clDefault, zsGZip); */

// NOTE: according to docs, you can leave outstream null, and instream 
// will be replaced and reused, but I could not get that to work

IdCompressorZLib1->CompressStream(                
    streamIn,            // System::Classes::TStream* AInStream,
    streamCompressed,    // System::Classes::TStream* AOutStream,
    1,                   // const Idzlibcompressorbase::TIdCompressionLevel ALevel,
    15 + 16,             // const int AWindowBits, -- add 16 to get gzip format
    8,                   // const int AMemLevel, -- see note below
    0);                  // const int AStrategy);

    streamCompressed->Position = 0;
    IdCompressorZLib1->DecompressGZipStream(streamCompressed, streamOut);

    String out = streamOut->DataString;
    ShowMessage(out);
}

特别注意,为 ALevel 传递 -1 会产生 ZLib 错误 -2,Z_STREAM_ERROR 这意味着无效参数,尽管我找到了默认值。此外,AWindowBits 的范围通常为 8 到 15,但添加 16 为您提供 gzip 格式,负数为您提供原始格式,如 zlib 库的作者之一 Mark Adler 引用的 zlib 文档中所述。根据 Mark Adler 的评论,我从 Indy 的默认值更改了 AMemLevel。

此外,如前所述,CompressStreamEx 函数将使用上述 cmets 中包含的参数生成 gzip 压缩。

以上内容在 RAD Studio XE3 中进行了测试。再次感谢您的帮助!

【讨论】:

  • memLevel 保留为默认值 8 通常会导致更好的压缩,因为可以更频繁地使 Huffman 代码适应数据。
  • 谢谢。我已经调整了上面的代码以反映这一点,并再次在 RAD Studio XE3 中进行了测试。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-10-28
  • 2018-03-27
  • 2014-04-21
  • 1970-01-01
  • 2014-05-29
相关资源
最近更新 更多