madZip Unit 

Content / madBasic /...
www.madshi.net

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;

// Example:
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;

// Example:
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;

// Example:
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;

// Example:
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;                      // full path
              const files : array of string;             // full path
              const zipAs : TDAString = nil) : boolean;  // only name, no path