There are a whole lot of situations where compression is useful. But often
compression components are either complicated to use or cost money or both.
So I've built my own little unit, which is based on the well known "zlib"
routines. I've thrown out a lot of stuff, though, reduced it all to the
absolutely necessary. E.g. I've chosen the compression factor which had for
my taste the best overall relation between compression speed, compression
size and code size - and removed all other compression factors. The
functions offered by madZip are as easy to use as they can be. But on the
other hand this unit does not offer fancy solutions. Not even the official
zip format is supported. Just plain data compression and uncompression. For
a quick overview of contained functions just look at the
madZip Reference.
Delphi strings are quite nice to use even for binary data, so my number one
compression wish was to have straight string (un)compression. The "Compress"
function has one predefined parameter: If you set "failIfGrow" to true, the
"Compress" function will return an empty string, if the compressed string is
longer than the original data.
 |
function Compress (data: string; failIfGrow: boolean = false) : string; overload;
function Uncompress (data: string ) : string; overload;
strVar := Compress('Does compressing this text really save much space??');
ShowMessage(Uncompress(strVar));
|
|
Sometimes you deal with plain pointers or buffers instead of with Delphi
strings. Of course there are functions for that purpose, too. Please note,
that the destination buffer should be 10% plus 12 bytes bigger than the
source buffer to make sure that the compression can fully run through.
 |
function Compress (src, dst: pointer; srcLen, dstLen: integer) : integer; overload;
function Uncompress (src, dst: pointer; srcLen, dstLen: integer) : integer; overload;
procedure CompressBufIntoStream(buf: pointer; len: integer; stream: TStream);
var temp : pointer;
begin
GetMem(temp, len * 11 div 10 + 12);
try
len := Compress(buf, temp, len, len * 11 div 10 + 12);
stream.WriteBuffer(temp^, len);
finally
FreeMem(temp);
end;
end;
|
|
Finally there are direct file compression/uncompression routines. Please
note, though, that the compressed file does *not* have the official zip
format. Instead it has no real format at all. It contains just the
compressed data (with a mini mini header).
 |
function Compress (srcFile, dstFile: string; failIfGrow : boolean = false) : boolean; overload;
function Uncompress (srcFile, dstFile: string; lastWriteTime: int64 = 0 ) : boolean; overload;
Compress('c:\autoexec.bat', 'c:\autoexec.$$$');
|
|
If you want to find out whether a compressed file is identical to another
uncompressed file, you can use the following function. It only compares the
(uncompressed) file sizes of the two files and the crc32 value. If this
function returns true, it is *probable* that the two files are identical,
but if you want to be 100% sure you will have to uncompress the compressed
file and compare them byte by byte.
 |
function IsCompressedFileEqual (uncomprFile, comprFile: string) : boolean;
if not IsCompressedFileEqual('c:\autoexec.bat', 'c:\autoexec.$$$') then
Compress('c:\autoexec.bat', 'c:\autoexec.$$$');
|
|
Since madZip internally needs a function which can calculate a crc32 value,
madZip can also export it for your personal use.
 |
function UpdateCrc32 (crc32: cardinal; const inBuf; inLen: integer) : cardinal;
|
|
You can create a "zip" compatible archive by calling the "Zip" function. The
first parameter is the full file path of the new zip archive. The second
parameter must be an array of the files you want to have zipped into the
archive (full file path again, please). The third array (only file names,
please) allows you to store the files into the zip under a different name.
Generally the resulting zip archive will not contain any directory
structure. All zipped files are directly stored in the archive's root.
 |
function Zip (zip : string;
const files : array of string;
const zipAs : TDAString = nil) : boolean;
|
|