Indy的TIdCompressorZLib.CompressStream方法的参数记录在哪里?

时间:2013-10-04 16:18:50

标签: delphi c++builder indy zlib

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来控制中使用的RLE编码策略   压缩操作。

在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;

但是,根据Z_DEFAULT_COMPRESSION

的文档,TIdCompressionLevel给出的值甚至不是该参数的合法值

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

谢谢!

2 个答案:

答案 0 :(得分:4)

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

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

答案 1 :(得分:3)

感谢您的评论和回答,特别是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文档中所述。根据马克·阿德勒的评论,我从印第安纳的默认值中改变了AMemLevel。

另外,如上所述,CompressStreamEx函数将使用上述注释中包含的参数生成gzip压缩。

以上是在RAD Studio XE3中测试的。再次感谢您的帮助!