Log In

Come Join Us!

Are you a
Computer / IT professional?
Join Tek-Tips Forums!
  • Talk With Other Members
  • Be Notified Of Responses
    To Your Posts
  • Keyword Search
  • One-Click Access To Your
    Favorite Forums
  • Automated Signatures
    On Your Posts
  • Best Of All, It's Free!
  • Students Click Here

*Tek-Tips's functionality depends on members receiving e-mail. By joining you are opting in to receive e-mail.

Posting Guidelines

Promoting, selling, recruiting, coursework and thesis posting is forbidden.

Students Click Here

Microsoft: FoxPro FAQ


How to Add Compression to a VFP Program Without ActiveX, Without $ by wgcs
Posted: 21 Jun 02 (Edited 19 Aug 04)

This is a Neat little way to add compression to your program.  Note: This compression is the Squeeze algorithm used by PkZip, but does not produce ".ZIP" compatible files... basically, it takes a string and produces a smaller string that can later be un-squeezed back to it's original state.

Because this uses the FileToStr and StrToFile VFP functions, it is limited to VFP's string handling limits, which appears to be limited to about 16MB per file (since it seems VFP uses three bytes (24 bits) to store the length of a string, so the largest string it can handle is 16777184 bytes long (ie, 2^24 - 24(length) - 8(null))

First, Get zLib from http://www.gzip.org/zlib/ (more specifically, the Win32 zLib.DLL at http://www.winimage.com/zLibDll/zlib114dll.zip ) and place it into your app's directory.

Now, create zLib.prg:


* zLib.prg
*  Author: William GC Steinford
*    Date: June 20, 2002
* Purpose: Easy to use Compress/Uncompress utilities
*            for VFP
    CASE upper(cFunc)='COMPRESS'
      RETURN CompressIt(cStr)
    CASE upper(cFunc)='UNCOMPRESS'
      RETURN UnCompressIt(cStr)
* Functions:
*!*    int compress (Bytef *dest, uLongf *destLen, const Bytef *source, uLong sourceLen);
*!*    int uncompress (Bytef *dest, uLongf *destLen, const Bytef *source, uLong sourceLen);

Function CompressIt( InFile )
DECLARE INTEGER compress IN zlib.dll AS zlibCompress ;
  STRING @ dest, INTEGER @ destLen, ;
  STRING src, INTEGER srcLen
* Compresses the source buffer into the destination buffer.
*   sourceLen is the byte length of the source buffer. Upon entry,
*   destLen is the total size of the destination buffer, which must
*   be at least 0.1% larger than sourceLen plus 12 bytes. Upon exit,
*   destLen is the actual size of the compressed buffer.
LOCAL lnSize, lcBuff, lnFinalSize
lnSize = len(InFile)
*123,456,789,012,345  15 chars is enough for 100 Terabytes.
lcBuff      = space( len(InFile)*1.2 )
lnFinalSize = len(lcBuff)
Res = zlibCompress( @lcBuff, @lnFinalSize, InFile, lnSize )
If Res=0 && Success
  RETURN PadL( alltrim(str(lnSize)), 15, '0' ) + Left( lcBuff, lnFinalSize )

* Proc UnCompressIt
*  The first 15 chars MUST be the (decimal) size of the uncompressed file
FUNCTION UnCompressIt( zLibFile )
DECLARE INTEGER uncompress IN zlib.dll AS zlibUnCompress ;
  STRING @ dest, INTEGER @ destLen, ;
  STRING src, INTEGER srcLen
* Decompresses the source buffer into the destination buffer.
*   sourceLen is the byte length of the source buffer. Upon entry,
*   destLen is the total size of the destination buffer, which must
*   be large enough to hold the entire uncompressed data.
* (The size of the uncompressed data must have been saved previously
*  by the compressor and transmitted to the decompressor by some mechanism
*  outside the scope of this compression library.)
*  Upon exit, destLen is the actual size of the compressed buffer.
* This function can be used to decompress a whole file at once if the input file is mmap'ed.
LOCAL lnSize, lcBuff, lnFinalSize
lnSize = len(zLibFile)
*123,456,789,012,345  15 chars is enough for 100 Terabytes.
lnFinalSize = Val( Left( zLibFile, 15 ) )
lcBuff      = space( lnFinalSize )
zLibFile    = SubStr( zLibFile, 16 )
Res = zlibUnCompress( @lcBuff, @lnFinalSize, zLibFile, lnSize )
If Res=0 && Success
  RETURN lcBuff

Now, you can use it in either of these manners:


  x = CompressIt( FileToStr("testfile.txt") )
  y = UnCompressIt( x )
  StrToFile( y, "testfile.txt.out" )

** OR **

  x = zLib("CompressIt", FileToStr("testfile.txt") )
  y = zLib("UnCompressIt", x )
  StrToFile( y, "testfile.txt.out" )

There's room for even more improvement...

Want to do multiple files?
Just create a table with two fields: "FileName" and "FileData" to keep track of a bunch of compressed files.
For example:


  SET PROC TO (srcDrv+"\source\las\zLib") ADDITIVE
  CREATE TABLE plg_Inst.dbf ;
    ( FileName   C(30), ;
      FileData   M,     ;
      Register   L,     ;
      Compressed L,     ;
      OrigSize   N(15)   )
  Select Plg_Inst
  fCnt = aDir( fArr, "*.HTM" )
  if fCnt > 0
    for fNum = 1 to fCnt
      append blank
      REPLACE FileName with fArr[fNum,1], ;
              FileData with CompressIt( FileToStr(fArr[fNum,1]) ), ;
              Compressed with .T.

Then when you want to extract them:


  if file('PLG_INST.DBF') and file('PLG_INST.FPT')
    * Copy DBF/FPT out because VFP has "issues" with
    *   accessing "included" FPT files.
    SELECT 0
    * Dump out all internal files!
      If not empty(Plg_inst.FileName) ;
         and not empty(Plg_inst.FileData)
        if Plg_Inst.Compressed
          lcCompFile   = Plg_Inst.FileData
          lcUnCompFile = zLib("UnCompressIt", lcCompFile )
          if not empty(lcUnCompFile)
            =StrToFile( lcUnCompFile, alltrim(Plg_Inst.FileName) )
            =MessageBox( 'Could not uncompress file "'+Plg_Inst.FileName+'".', mbxOk)
          =StrToFile( Plg_Inst.FileData, alltrim(Plg_Inst.FileName) )
    =MessageBox('Error Installing additional files!',mbxOk,'')

In some ways, it isn't Quite as good as having a real .ZIP file (you can't extract the files outside of VFP), but in some way's its Better:
    [li]It's easy to include/extract the files from a .APP/.EXE file (so you can distribute only One file)
    [li]It's all within VFP (no ActiveX to register, no MsVCrt support files)
    [li]It's Small (only 53k)
    [li]It's Free!!

Back to Microsoft: FoxPro FAQ Index
Back to Microsoft: FoxPro Forum

My Archive

Close Box

Join Tek-Tips® Today!

Join your peers on the Internet's largest technical computer professional community.
It's easy to join and it's free.

Here's Why Members Love Tek-Tips Forums:

Register now while it's still free!

Already a member? Close this window and log in.

Join Us             Close