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组件的来源?
谢谢!
答案 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中测试的。再次感谢您的帮助!