Saturday, September 30, 2006

Blog Entry Updated (09/30/2006 7:00 PM): Corrected the signature and documentation for the UnzipQuick function. Added links that were missing.
Blog Entry Updated (09/30/2006 9:00 PM): Corrected documentation regarding ignore path(s) parameters - Thanks Sergey Berezniker.
Blog Entry Updated (10/01/2006 9:36 PM): Added documentation regarding new UnzipAFileInfo and UnzipAFileInfoByIndex functions - Thanks Bo Durban.
Blog Entry Updated (10/02/2006 12:27 AM): Corrected the signature for UnzipAFileInfo function. - Thanks Malcolm Greene.
Blog Entry Updated (10/15/2006 7:25 AM): Modified Example #6 to show alternate syntax.

VFPCompression Library

I debuted the VFPCompression FLL in my previous blog entry and here I am going to provide an updated copy of it along with the documentation. One of the things that I added to this FLL that might be of particular interest is the ability to compress and uncompress strings (think xml, client-server, and/or memo files near 2GB range). This FLL was made possible by the Zlib compression Library and code found in an article out on Code Project.  This FLL is provided freely to be used and abused in whatever manner you see fit, including in commercial applications. The only restriction I place on it is that you don't sue me or SweetPotato Software, Inc. for damages related to the use or abuse of this FLL. :)

Possible future features

  • Progress callback - would report percentage complete to a user-defined VFP function
  • Status callback - would report status of zip/unzip to a user-defined VFP function
  • Cancel function - would allow developer to cancel zip/unzip at any point during a zip/unzip operation
  • Self-extracting Zip - fully support the self-extracting zip format
  • Encryption - Allow encrypted zips to be created and extracted
  • Password Protect - support password protection for zip files
  • Disk Spanning - support the ability to span multiple disks or otherwise split zip files into smaller portions (create and extract)

What you can do (if you want)

I would appreciate feedback regarding this FLL and bug reports when problems are encountered. I think that's a fair trade if you've found this FLL useful and it will help me improve it for the benefit of the entire VFP Community. Also, if you have any suggestions for improving this FLL (such as new features) please don't hesitate to post a comment here in this blog or send me an email.

That having been said, here is the updated download, sample VFP code, and the documentation for the FLL...

VFP Compression Update:

VFPCompression FLL Download (33 KB approx.)

VFP Compression Sample Code:

*!* Example 1
SET LIBRARY TO LOCFILE("vfpcompression.fll")
    ?ZipFileQuick("C:\MyFile.txt")
SET LIBRARY TO

*!* Example 2
SET LIBRARY TO LOCFILE("vfpcompression.fll")
    ?ZipFolderQuick("C:\MyFolder")
SET LIBRARY TO

*!* Example 3
SET LIBRARY TO LOCFILE("vfpcompression.fll")
    ?UnzipQuick("C:\MyFile.zip", "C:\")
    ?UnzipQuick("C:\MyFolder.zip", "C:\")
SET LIBRARY TO

*!* Example 4
SET LIBRARY TO LOCFILE("vfpcompression.fll")
    ?ZipOpen("C:\MyZipFile.zip", "C:\", .F.)
    ?ZipFile("C:\SomeFile.txt", .F.)
    ?ZipClose()
SET LIBRARY TO

*!* Example 5
SET LIBRARY TO LOCFILE("vfpcompression.fll")
?UnzipQuick("C:\MyZipFile.zip","C:\",.F.)
SET LIBRARY TO

*!* Example 6
SET LIBRARY TO LOCFILE("vfpcompression.fll")
    ?ZipOpen("C:\MyZipFile.zip")

    *!* ?ZipOpen("MyZipFile.zip", "C:\", .F.)
    ?ZipFolder("C:\MyFolder", .F.)
    ?ZipClose()
SET LIBRARY TO

*!* Example 7
SET LIBRARY TO LOCFILE("vfpcompression.fll")
CLEAR
lcOriginal = REPLICATE("Visual FoxPro Rocks!",100)
?"Original Length: " + TRANSFORM(LEN(lcOriginal))
?
lcCompressed = ZipString(lcOriginal)
?"Compressed: " + lcCompressed
?"Compressed Length: " + TRANSFORM(LEN(lcCompressed))
?
?"Length Savings: " + TRANSFORM(LEN(lcOriginal) - LEN(lcCompressed)) + " bytes"
?
lcUncompressed = UnzipString(lcCompressed)
*!* ?"Uncompressed: " + lcUncompressed
?"Uncompressed Length: " + TRANSFORM(LEN(lcUncompressed))
?"Equals Original: " + IIF(lcUncompressed == lcOriginal, "YES", "NO")
IF !(lcUncompressed == lcOriginal)
EXIT
ENDIF
SET LIBRARY TO

VFP Compression Documenation:

Function ZipString()

Signature: ZipString(cString[, nLevel])

Parameters:

cString - The character string you wish to compress

nLevel - The compression level to use which is 1 through 9 (1 is the fastest, while 9 is the best compression). The default value for this parameter is 6.

Return Value:

Character Data - the compressed version of cString.

Remarks:

This function is particularly useful in a client-server application given that strings of data (such as memo fields, character fields, and xml) can be compressed before sending them across the network and then extracted at the other end (using UnzipString).


Function ZipFileQuick()

Signature: ZipFileQuick(cFileName)

Parameters:

cFileName - The fully qualified file name (full path) of the file you wish to have compressed.

Return Value:

Logical - returns .T. if successful or .F. if the operation has failed.

Remarks:

The zip file that this function creates will have the same file name as cFileName, with the extension as ".zip".


Function ZipFolderQuick()

Signature: ZipFileQuick(cFolderName)

Parameters:

cFolderName - The full path to the folder you wish to have zipped.

Return Value:

Logical - returns .T. if successful or .F. if the operation has failed.

Remarks:

The zipfile that this function creates will have the same file name as cFolderName, with the extension as ".zip".


Function ZipOpen()

Signature: ZipOpen(cZipFileName[,cFolderName[,lAppend]])

Parameters:

cZipFileName - The file name or full path of the zip file you wish to create.

cFolderName - The full path of the folder in which you want cZipFileName created.

lAppend - If the zip file you are compressing to exists you can choose to append to it by passing .T. to this parameter. Defaults to .F..

Return Value:

Logical - returns .T. if successful or .F. if the operation has failed.

Remarks:

ZipOpen() is used in conjunction with the matching ZipClose(). The usual series of function calls would consist of creating/opening the zip file using ZipOpen, zipping files and/or folders using ZipFile/ZipFileRelative/ZipFolder, and then closing the zip file using ZipClose.


Function ZipClose()

Signature: ZipClose()

Parameters: None

Return Value:

Logical - returns .T. if successful or .F. if the operation has failed.

Remarks:

ZipClose() must be called after issuing a ZipOpen(). The usual series of function calls would consist of creating/opening the zip file using ZipOpen, zipping files and/or folders using ZipFile/ZipFileRelative/ZipFolder, and then closing the zip file using ZipClose.


Function ZipFile()

Signature: ZipFile(cFileName[,lIgnorePath])

Parameters:

cFileName - The file name or full path of the file you wish to compress.

lIgnorePath - If you wish to ignore the relative path of the file into the zip file that is being created you would pass .T. for this parameter. The default value for this parameter is .F. which means that the relative path will be respected.

Return Value:

Logical - returns .T. if successful or .F. if the operation has failed.

Remarks:

ZipFile() is used between calls to ZipOpen() and ZipClose(). The usual series of function calls would consist of creating/opening the zip file using ZipOpen, zipping files and/or folders using ZipFile/ZipFileRelative/ZipFolder, and then closing the zip file using ZipClose.


Function ZipFileRelative()

Signature: ZipFileRelative(cFileName[,cRelativePath])

Parameters:

cFileName - The file name or full path of the file you wish to compress.

cRelativePath - The relative path you wish to have saved in the zip for this file. This allows you to set up the structure (relative paths) in the zip different from the actual relative paths of the files you are compressing.

Return Value:

Logical - returns .T. if successful or .F. if the operation has failed.

Remarks:

ZipFileRelative() is used between calls to ZipOpen() and ZipClose(). The usual series of function calls would consist of creating/opening the zip file using ZipOpen, zipping files and/or folders using ZipFile/ZipFileRelative/ZipFolder, and then closing the zip file using ZipClose.


Function ZipFolder()

Signature: ZipFolder(cFolderName[,lIgnorePaths])

Parameters:

cFolderName - The full path to the folder you wish to compress.

lIgnorePaths - If you wish to ignore the relative path of the folder into the zip file that is being created you would pass .T. for this parameter. The default value for this parameter is .F. which means that paths will be respected.

Return Value:

Logical - returns .T. if successful or .F. if the operation has failed.

Remarks:

ZipFolder() is used between calls to ZipOpen() and ZipClose(). The usual series of function calls would consist of creating/opening the zip file using ZipOpen, zipping files and/or folders using ZipFile/ZipFileRelative/ZipFolder, and then closing the zip file using ZipClose.


Function UnzipString()

Signature: UnzipString(cString)

Parameters:

cString - The compressed string you wish to uncompress.

Return Value:

Character Data - the extracted version of cString.

Remarks:

The string to be extracted must have been compressed with the ZipString() function or other compression function that is compatible with the compress or compress2 functions in zlib.


Function UnzipQuick()

Signature: UnzipQuick(cZipFileName, cOutputFolderName[, lIgnorePaths])

Parameters:

cZipFileName - The fully qualified file name (full path) of the zip file you wish to have extracted.

cOutputFolderName - The full path to the folder you wish to extract the contents of the zip to.

lIgnorePaths - If you wish to ignore the relative paths that are contained in the zip file you would pass .T. for this parameter. The default value for this parameter is .F. which means that the relative paths will be respected.

Return Value:

Logical - returns .T. if successful or .F. if the operation has failed.

Remarks:

The file and folders in the zip file will be extracted into the same folder as the cZipFileName resides in.


Function UnzipOpen()

Signature: UnzipOpen(cZipFileName)

Parameters:

cZipFileName - The file name or full path of the zip file you wish to uncompress.

Return Value:

Logical - returns .T. if successful or .F. if the operation has failed.

Remarks:

UnzipOpen() is used in conjunction with the matching UnzipClose(). The usual series of function calls would consist of opening the zip file using UnzipOpen, uncompressing files and/or folders using Unzip/UnzipTo/UnzipByIndex/UnzipFile, and then closing the zip file using UnzipClose.


Function UnzipClose()

Signature: UnzipClose()

Parameters: None

Return Value:

Logical - returns .T. if successful or .F. if the operation has failed.

Remarks:

UnzipClose() must be called after issuing an UnzipOpen(). The usual series of function calls would consist of opening the zip file using UnzipOpen, uncompressing files and/or folders using Unzip/UnzipTo/UnzipByIndex/UnzipFile, and then closing the zip file using UnzipClose.


Function Unzip()

Signature: Unzip()

Parameters: None

Return Value:

Logical - returns .T. if successful or .F. if the operation has failed.

Remarks:

Unzip() is used between calls to UnzipOpen() and UnzipClose() to uncompress the entire zip file. The files and folders contained in the zip file will be extracted to the same folder as the zip file resides in unless a call to UnzipSetFolder() has been previously issued. The usual series of function calls would consist of opening the zip file using UnzipOpen, uncompressing files and/or folders using Unzip/UnzipTo/UnzipByIndex/UnzipFile, and then closing the zip file using UnzipClose.


Function UnzipTo()

Signature: UnzipTo(cOutputFolderName[, lIgnorePaths])

Parameters:

cOutputFolderName - The folder into which the zip file contents should be extracted.

lIgnorePaths - If you wish to ignore the relative paths that are contained in the zip file you would pass .T. for this parameter. The default value for this parameter is .F. which means that the relative paths will be respected.

Return Value:

Logical - returns .T. if successful or .F. if the operation has failed.

Remarks:

UnzipTo() is used between calls to UnzipOpen() and UnzipClose(). The functionality of this is similar to calling UnzipSetFolder() and then Unzip(). The usual series of function calls would consist of opening the zip file using UnzipOpen, uncompressing files and/or folders using Unzip/UnzipTo/UnzipByIndex/UnzipFile, and then closing the zip file using UnzipClose.


Function UnzipFile()

Signature: UnzipFile(cOutputFolderName[, lIgnorePaths])

Parameters:

cOutputFolderName - The folder into which the current file (cotained in the zip) should be extracted.

lIgnorePaths - If you wish to ignore the relative path of the current file you would pass .T. for this parameter. The default value for this parameter is .F. which means that the relative path will be respected.

Return Value:

Logical - returns .T. if successful or .F. if the operation has failed.

Remarks:

UnzipFile() is used between calls to UnzipOpen() and UnzipClose() to extract the currently selected file contained in the zip file. UnzipFile() is used in conjunction with the UnzipGotoTopFile, UnzipGotoNextFile, UnzipGotoFileByName, and UnzipGotoFileByIndex functions. You can think of the contents of a zip file as records in a table. In this sense UnzipGotoTopFile, UnzipGotoNextFile, UnzipGotoFileByName, and UnzipGotoFileByIndex functions are used to move the record pointer and the UnzipFile function is used to extract the file that the record pointer is currently on.


Function UnzipByIndex()

Signature: UnzipByIndex(nIndex[, cOutputFolderName[,lIgnorePaths]])

Parameters:

nIndex - The index number of the file to be extracted.

cOutputFolderName - The folder into which the zip file contents should be extracted.

lIgnorePaths - If you wish to ignore the relative path for this file that is contained in the zip file you would pass .T. for this parameter. The default value for this parameter is .F. which means that the relative path will be respected.

Return Value:

Logical - returns .T. if successful or .F. if the operation has failed.

Remarks:

UnzipByIndex() is used between calls to UnzipOpen() and UnzipClose() to extract a file by the position (index) it holds in the zip file. UnzipByIndex() is used in conjunction with the UnzipFileCount function. You can think of the contents of a zip file as records in a table. In this sense UnzipFileCount would give you the record count for the table and the UnzipByIndex function be used to extract a particular file by record number.


Function UnzipFileCount()

Signature: UnzipFileCount()

Parameters: None

Return Value:

Logical - returns .T. if successful or .F. if the operation has failed.

Remarks:

UnzipFileCount() is used between calls to UnzipOpen() and UnzipClose() to retrieve the number of files that are contained in the zip file. It does not actually extract anything. UnzipFileCount() is used in conjunction with the UnzipByIndex function. You can think of the contents of a zip file as records in a table. In this sense UnzipFileCount would give you the record count for the table and the UnzipByIndex function be used to extract a particular file by record number.


Function UnzipSetFolder()

Signature: UnzipSetFolder(cOutputFolderName)

Parameters:

cOutputFolderName - The folder into which the zip file contents should be extracted.

Return Value:

Logical - returns .T. if successful or .F. if the operation has failed.

Remarks:

UnzipSetFolder() is used between calls to UnzipOpen() and UnzipClose() to set the output folder for extracted zip contents. It does not actually extract anything. The usual series of function calls would consist of opening the zip file using UnzipOpen, calling UnzipSetFolder to set the output folder, uncompressing files and/or folders using Unzip/UnzipTo/UnzipByIndex/UnzipFile, and then closing the zip file using UnzipClose.


Function UnzipGotoTopFile()

Signature: UnzipGotoTopFile([cExtension])

Parameters:

cExtension - The file extension to use as a filter for file type. All other file types will be ignored and only the first file of the type specified will be selected in the zip file.

Return Value:

Logical - returns .T. if successful or .F. if the operation has failed.

Remarks:

UnzipGotoTopFile() is used between calls to UnzipOpen() and UnzipClose() to select a particular file in the contents of the open zip file. UnzipGotoTopFile() is used in conjunction with the UnzipFile function to extract a particular file from the zip. By using the cExtension optional parameter you can select the first record of a particular file type. You can think of the contents of a zip file as records in a table. In this sense UnzipGotoTopFile, UnzipGotoNextFile, UnzipGotoFileByName, and UnzipGotoFileByIndex functions are used to move the record pointer and the UnzipFile function is used to extract the file that the record pointer is currently on.


Function UnzipGotoNextFile()

Signature: UnzipGotoNextFile([cExtension])

Parameters:

cExtension - The file extension to use as a filter for file type. All other file types will be ignored and only the next file of the type specified will be selected in the zip file.

Return Value:

Logical - returns .T. if successful or .F. if the operation has failed.

Remarks:

UnzipGotoNextFile() is used between calls to UnzipOpen() and UnzipClose() to select a particular file in the contents of the open zip file. UnzipGotoNextFile() is used in conjunction with the UnzipFile function to extract a particular file from the zip. By using the cExtension optional parameter you can select the next record of a particular file type. You can think of the contents of a zip file as records in a table. In this sense UnzipGotoTopFile, UnzipGotoNextFile, UnzipGotoFileByName, and UnzipGotoFileByIndex functions are used to move the record pointer and the UnzipFile function is used to extract the file that the record pointer is currently on.


Function UnzipGotoFileByName()

Signature: UnzipGotoFileByName(cFileName[, lIgnoreFilePath])

Parameters:

cFileName - The file name of the file you wish to select in the zip file contents. You can specify a relative path as well to narrow down the search.

lIgnoreFilePath - If you wish to just find a file of a particular name in the zip file you can pass .T. for this parameter and the relative path of the file will be ignored. The first matching file of the name specified in cFileName will be selected in the zip contents.

Return Value:

Logical - returns .T. if successful or .F. if the operation has failed.

Remarks:

UnzipGotoFileByName() is used between calls to UnzipOpen() and UnzipClose() to select a particular file in the contents of the open zip file by file name and/or relative path. UnzipGotoFileByName() is used in conjunction with the UnzipFile function to extract a particular file from the open zip file. You can think of the contents of a zip file as records in a table. In this sense UnzipGotoTopFile, UnzipGotoNextFile, UnzipGotoFileByName, and UnzipGotoFileByIndex functions are used to move the record pointer and the UnzipFile function is used to extract the file that the record pointer is currently on.


Function UnzipGotoFileByIndex()

Signature: UnzipGotoFileByIndex([nIndex])

Parameters:

nIndex - The index number of the file to be selected.

Return Value:

Logical - returns .T. if successful or .F. if the operation has failed.

Remarks:

UnzipGotoFileByIndex() is used between calls to UnzipOpen() and UnzipClose() to select a particular file by the position it physically holds in the contents of the open zip file. UnzipGotoFileByIndex() is used in conjunction with the UnzipFile function to extract a particular file from the zip file contents. You can think of the contents of a zip file as records in a table. In this sense UnzipGotoTopFile, UnzipGotoNextFile, UnzipGotoFileByName, and UnzipGotoFileByIndex functions are used to move the record pointer and the UnzipFile function is used to extract the file that the record pointer is currently on.


Function UnzipAFileInfoByIndex()

Signature: UnzipAFileInfoByIndex(cArrayName, nIndex)

Parameters:

cArrayName - Name of the VFP array to be created with file information in it.

nIndex - The index number of the file you want to return information about.

Return Value:

Logical - returns .T. if successful or .F. if the operation has failed.

Creates an array with 13 rows (elements) in it. The rows contain various pieces of information regarding the file that is held in the zip file at nIndex. The following table describes the contents and data type of each row in the array:

Row Array Content Data Type
1 File Name Character
2 Comment Character
3 Version Numeric
4 Version Needed Numeric
5 Flags Numeric
6 Compression Method Numeric
7 DOS Date Datetime
8 CRC Numeric
9 Compressed Size Numeric
10 Uncompressed Size Numeric
11 Internal Attribute Numeric
12 External Attribute Numeric
13 Folder Logical

Remarks:

The array that is created will have whatever name was specified by cArrayName. Should the array already exist it will release it and recreate it. UnzipAFileInfoByIndex() is used between calls to UnzipOpen() and UnzipClose() to show information about a particular file. The file is referred to by the position it physically holds in the contents of the open zip file. You can think of the contents of a zip file as records in a table. In this sense the UnzipAFileInfoByIndex function is used to refer to and retrieve information about a particular record number in the zip file.


Function UnzipAFileInfo()

Signature: UnzipAFileInfo(cArrayName)

Parameters:

cArrayName - Name of the VFP array to be created with file information in it.

Return Value:

Logical - returns .T. if successful or .F. if the operation has failed.

Creates an array with 13 rows (elements) in it. The rows contain various pieces of information regarding the currently selected file in the zip. The following table describes the contents and data type of each row in the array:

Row Array Content Data Type
1 File Name Character
2 Comment Character
3 Version Numeric
4 Version Needed Numeric
5 Flags Numeric
6 Compression Method Numeric
7 DOS Date Datetime
8 CRC Numeric
9 Compressed Size Numeric
10 Uncompressed Size Numeric
11 Internal Attribute Numeric
12 External Attribute Numeric
13 Folder Logical

Remarks:

The array that is created will have whatever name was specified by cArrayName. Should the array already exist it will release it and recreate it. UnzipAFileInfo() is used between calls to UnzipOpen() and UnzipClose() to show information about a particular file. Use the UnzipAFileInfo function in conjunction with UnzipGotoTopFile, UnzipGotoNextFile, UnzipGotoFileByName, and UnzipGotoFileByIndex functions to return information regarding a particular file contained in the open zip file. You can think of the contents of a zip file as records in a table. In this sense the UnzipAFileInfo function is used to refer to and retrieve information about the record that the record pointer is currently on within the zip file.

Saturday, September 30, 2006 11:03:46 PM (Central Daylight Time, UTC-05:00)  #    Comments [20]
Sunday, October 01, 2006 1:09:51 AM (Central Daylight Time, UTC-05:00)
WOW! What an impressive library. Thanks for putting this together Craig.

The implications of ZIPping strings are ENORMOUS, especially for large memo fields. You can ZIPString on your INSERT and UNZIPString on your SELECT. Very COOL!. This would also be useful in a web environment. The speed is incredible. I just zipped an 8.2MB string, down to 62KB in 0.18 seconds. That’s over 99% compression.

FYI, I tested the library on a large ZIP file (1.2GB zipped, 3.8GB unzipped). It unzipped all 680 files in about 220 seconds (it took the same amount of time using WinZIP 10). It looks like this thing is ready for some heavy duty use.

I look forward to the new features you mentioned. Encryption, callbacks, etc… It would also be nice to have some additional features:

- Some type of information about the zipped files, similar to ADIR. Have it include info like: FileName, Path, Orig. size, Compressed size, Modified date, etc…

- Ability to specify an array of files to be compressed

Thanks again. GREAT JOB!!!!
Sunday, October 01, 2006 2:43:17 PM (Central Daylight Time, UTC-05:00)
Great library! Good job.
Bo had some good suggestions,especially when it comes to info about the contained files.

I would suggest that an optional second/third parameter be used for the Quick functions to specify a zipfile.
Josh Assing
Monday, October 02, 2006 9:16:29 AM (Central Daylight Time, UTC-05:00)
Thanks for this great lib!

How does it handle files that may be open/locked at an OS level?
Alan Bourke
Monday, October 02, 2006 10:32:54 AM (Central Daylight Time, UTC-05:00)
Hi Alan,

Good question... I would think that it would fail and return .F. from the functions. However, I haven't tested that particular scenario. Maybe you could give it a quick go and then report back? If it does fail, there might be something I can do.
Monday, October 02, 2006 8:44:03 PM (Central Daylight Time, UTC-05:00)
Great job, Craig! When you get around to plugging in a progress dialog, take a look at the source code for Gregory Adam's callback FLL (vfp.fll) at the UT (Download ID: 20453). Shows how to link VFP PROCEDURE calls to callbacks in an FLL or DLL.
Tuesday, October 03, 2006 6:47:24 PM (Central Daylight Time, UTC-05:00)
Hi Craig,

OK, I'm able to make this work now (awesome job!). My problem was with the relative paths, which the documentation helped me to sort out. If the second parameter passed to ZipFile() or ZipFolder() is .F., and the ZIP file being created is NOT in the folder hierarchy at or above the file/folder being ZIPped, then the function will fail. For example, ZipFolder( "C:\MyApp\Data", .F. ) will succeed only if the ZIP file is being created in C:\, C:\MyApp, or C:\MyApp\Data. Attempting to create the ZIP file anywhere else will cause ZipFolder() to fail. ZipFileRelative() would be the solution when zipping individual files, but will there be a corresponding ZipFolderRelative() for folders (I don't see that in the documentation)?

I also have one enhancement request (for now :-)). When zipping an entire folder, I would like a way to exclude subfolders, probably as an additional parameter passed to the functions which zip folders. This would be very useful for backing up a data folder, for instance, which might have numerous backup folders below it which need to be excluded.

Thanks a ton! Having such a fast, free, easy to use and install tool like this is truly mind-boggling!
Mike Potjer
Wednesday, October 04, 2006 8:55:10 AM (Central Daylight Time, UTC-05:00)
Sam,
Thanks for the kind words and the tip. I'll definitely take a look at Gregory Adam's callback FLL.

Mike,
Glad it's working for you and I'll take a look at the issue you've presented. I think your enhancement request is a good one and I'll add it to the list (some kind of lRecurseSubDirs parameter - default to .T.).
Wednesday, October 04, 2006 8:14:05 PM (Central Daylight Time, UTC-05:00)
Very nice. Thanks for posting. Do the zip directory functions support exluding files by extension? (ala Dynazip's excludefiletypes="*.BAK *.ZIP *.TBK")
ChrisO
Friday, October 06, 2006 9:40:01 PM (Central Daylight Time, UTC-05:00)
ChrisO,

Thank you. The FLL does not currently support a wildcard mask or delimited extension list for zipping. However, that is a pretty good enhancement request. I will add it to the list. Thanks for the suggestion.
Tuesday, November 14, 2006 10:12:08 PM (Central Standard Time, UTC-06:00)
Hello Craig,
Thank you for your great work.

I had some problem with ZIPSTRING/UNZIPSTRING. I have some large strings (100k) where UNZIPSTRING returns an empty value for the string just zipped with ZIPSTRING.
But, there is no problem if a put this strings into files and then zip/unzip on files.

Is there any way to give you this strings?

Thank you.
Petre Popescu
Wednesday, January 10, 2007 12:14:58 PM (Central Standard Time, UTC-06:00)
Hi Craig,

But do you have already a solution for the problem on creating archives that are not on the same drive letter as the collected files?
That is a great problem in my opinion, because if you have not enough space left on the source drive, than you can't generate the zip-file. Or in my case, I can't put my zip-file directly in the appropriate folder on our network drive.

Is there a great possibility to fix this problem in short time?
Because this tool is the best available zip-compressor for foxpro programmers and I would like to use it furthermore.

Many thanks,
Martin
Friday, February 09, 2007 2:32:48 PM (Central Standard Time, UTC-06:00)
Hi Craig,

You library is great.
But have problem , i just bought new computer os windowsxppsb2. When i trying to load you library, i got error message "library file c:\vfpcompression.fll is invalid ?
Why? What the problem,and where it to find, because i try other computer with the same os,everyting is ok.....

I waiting for you answer...


Many thanks,
Mindaugas
Mindaugas
Saturday, March 31, 2007 8:49:39 AM (Central Daylight Time, UTC-05:00)
Hi !

We are getting problem, when i trying to load library "vfpcompression.fll".
I got an error message "library file vfpcompression.fll is invalid ?".

I'm using Win2k prof. with sp4. This library is working on the other system with the same configuration. Pls help me to solve this problem.


Thanks
Ravi Mehrotra
Ravi Mehrotra
Wednesday, August 08, 2007 8:25:56 AM (Central Daylight Time, UTC-05:00)
Hi,

Is this library require any other supporting runtime libraries i.e c++ runtime library.

Thanks
Ravi Mehrotra
Ravi Mehrotra
Friday, August 10, 2007 9:37:32 AM (Central Daylight Time, UTC-05:00)
Hi Ravi,

It requires the msvcr71.dll which is one of the VFP 9 runtime libraries. So, if you are running VFP 9 apps then no other files are needed, if you are running earlier VFP version then you will need msvcr71.dll installed where vfpcompression.fll can find it.
Wednesday, October 03, 2007 2:36:37 PM (Central Daylight Time, UTC-05:00)
Hi Craig,

thanks for the great work on this. Just a couple things I picked up in the documentation on this page:

1. Function UnzipFileCount() says it returns Logical, but it actually returns an integer value

2. Function UnzipByIndex() does not mention that the index is zero based, which luckily I figured out by experimentation.

Thanks again.

Frank
Frank Cazabon
Wednesday, January 09, 2008 5:40:29 AM (Central Standard Time, UTC-06:00)
I face a problem, while zipping. Library create new zip file and return .T., some images zipped into last opened zip file and it returns .T. to all files it was zipped, and close successfully (.T.), but when we check physically 'FILE NOT FOUND ON HARD-DISK'. All hardwares are OK. In average while checking logs, 20 to 60 zip files not found over 1000 files. As it return .t. each time.

Where is the problem?
NEERAJ SHOREY
Saturday, January 12, 2008 12:17:34 AM (Central Standard Time, UTC-06:00)
Neeraj,

No one else has reported this sort of problem. If the files exist on disk, and you are passing the right full path, and you have proper permissions to read those files then they should be being zipped. As the FLL uses zlib the compression is considered reliable and not error prone as your post suggests. Is there any pattern to the problem (are the same files missed every time for instance)? Is the problem readily reproduceable and if so what would I need to set up at this end to reproduce what you are seeing? If you are zipping files from different directories that are not relative to where the zip is being created make sure that you are using the lIgnoreFilePath parameter and setting it to .T.

Lastly, perhaps you could send me a snippet of the code you are using and I could review it for you and ascertain whether there is anything obvious that might be causing a problem.
Thursday, January 24, 2008 10:22:37 AM (Central Standard Time, UTC-06:00)
This little utility is very cool. It saved my day because I needed to email reports out of a VFP app. The document, however, got rejected by our mailserver due to its size. Your zip routine resolved this very nicely.

However, when exporting bits and pieces of my data to Excel and zipping them the files are still too large to be sent.
Is it possible to create multi-zip from a (huge) so I can create 3Mb files that I can sent through our mail-server? This feature would be awesome to have. Any thoughts?

Thanks!
Thursday, March 27, 2008 8:22:04 PM (Central Daylight Time, UTC-05:00)
Craig,

As the others said, thanks for this great tool. I've been using it for a little while now, but yesterday I needed to generate a zip file with the full path to the files stored in the zip file. It seems I could not do that. I theorize that I could create the zip file in the root of the C: drive and this would force it to use the full path (have not tested this, yet), then I could copy the zip file to where I actually need it to be, but it would be nice to be able to just tell it to store the full path. Perhaps I'm missing something? If not, please put it on the enhancement request list.

Thanks again,

Russell Campbell
Russell Campbell
Name
E-mail
(will show your gravatar icon)
Home page

Comment (Some html is allowed: a@href@title, b, blockquote@cite, em, i, strike, strong, sub, super, u)  

Enter the code shown (prevents robots):


 

Archive

<August 2008>
SunMonTueWedThuFriSat
272829303112
3456789
10111213141516
17181920212223
24252627282930
31123456