Pascal Newsletter #5
The full source code examples of this issue are available for download.
![]() |
![]() |
Pascal Newsletter #5 INDEX 1. A FEW WORDS FROM THE EDITOR 2. FREE PASCAL 3. DELPHI ZIP a) Where to get it? b) Installation c) Trying the demo d) How does it work? 1) Creating a new archive 2) Adding files to an archive 3) Adding files to an archive in multiple volumes 4) Deleting files from an archive 5) Extracting files from an archive 6) Testing an archive 7) Intercepting the messages 8) Listing the files stored in the archive ________________________________________________________________________ 1. A FEW WORDS FROM THE EDITOR Our new web site is now working... or at least it should be! ;) http://www.latiumsoftware.com/en/ It's the same stuff, nothing new so far, but this month probably we will start adding material more or less continuously if we can. We'll keep you posted. In the last issue we printed wwww instead of www in the address of our site, so if you couldn't enter the site, now you know why! ;) Oops! Thanks to Alejandro who pointed this out. Regards, Ernesto De Spirito eds2004 @ latiumsoftware.com ________________________________________________________________________ JfControls Library. Multi-language. Multi-appearance. Skins. Privileges. More than 40 integrated and customizable components. Impressive GUI. Centralized resources administration. Multiple programming problems solved. For Delphi 3-7 and C++ Builder 3-6. http://www.jfactivesoft.com/ ________________________________________________________________________ 2. FREE PASCAL Version 1.00 of this pascal compiler was officially released last July, and it is expected that little by little it will start being included in many Linux distributions. It is available as RPM, .deb and .tar.gz packages. But Free Pascal is not only for Linux, since it is also available for DOS (requires the GO32 extender), 32-bit Windows, OS/2 (requires the EMX extender) and Amiga (Version 0.99.5). If you wish to download it, go to http://www.freepascal.org/sdown.html We suggest you choose a mirror, because the main site is usually very slow. ________________________________________________________________________ 3. DELPHI ZIP This is a set of freeware Delphi components and a demo application (with full source code included) that access ZIP files using the ZIPDLL and UNZDLL DLLs of the Info-Zip Project. They work on all 32-bit versions of Delphi (from 2 to 5). a) Where to get it? =================== It is available at: BCB and Delphi Freeware Zip Components http://www.geocities.com/SiliconValley/Orchard/8607/ http://members.tripod.lycos.nl/Vleghert/ I downloaded the following files: * Delphi Zip 1.6L beta release (360K) http://www.geocities.com/SiliconValley/Orchard/8607/beta/dz-del160.zip http://members.tripod.lycos.nl/Vleghert/beta/dz-del160.zip * TZipMaster 1.6L help file (81K) http://www.geocities.com/SiliconValley/Orchard/8607/beta/zipmst16.zip http://members.tripod.lycos.nl/Vleghert/beta/zipmst16.zip The first archive has it all, except the help file of the TZipMaster component, and the source code of the DLLs: * ZipDll and UnZDll source files for BCB 3 or BCB 4 (241K) http://www.geocities.com/SiliconValley/Orchard/8607/dz-dllsrc15.zip I didn't download them because they are for C++ Builder. The DLLs are included in the main archive (dz-del160.zip) and there are also optimized versions available, like: * Pentium DLLs. Compiled with BCB 4 optimized for Pentium (129K) http://www.geocities.com/SiliconValley/Orchard/8607/pendll15.zip b) Installation =============== 1) Unzip dz-del160.zip in a temporal directory and run dz-del160.exe to install. It will prompt you for an installation directory. I chose "C:\Delphi\Zip", but you con extract it anywhere you like it (just substitute "C:\Delphi\Zip" with your path). 2) Copy or move these files to your Windows\System directory: C:\Delphi\Zip\DLL\*.DLL and C:\Delphi\Zip\SFX\*.BIN 3) Now you should either copy or move "C:\Delphi\Zip\VCL\*.*" files to a directory in the VCL path, or include "C:\Delphi\Zip\VCL" in your VCL path (in Delphi 5 select Environment Options from the Tools menu and add this directory to the Library Path and Browsing Path). 4) Install the VCL components. How? This is ABC! You should know how! :) Ok, start Delphi 5. Select Close All from the File menu and select Install Component from the Component menu. Click Browse to select the unit files and select all *.pas files in the "C:\Delphi\Zip\VCL" directory (or where you placed these files) and click Open and then OK to compile. Finally close the package and save it when prompted. If you have a previous version of Delphi, follow the instructions provided in "C:\Delphi\Zip\Install.txt". 5) Install the help files. How? This is ABC! You should know how! :) Ok, unzip zipmst16.zip and move the two files to your Delphi Help directory (for example "C:\Program files\Borland\Delphi5\Help"). Edit delphi5.cnt and add these two lines with the others: :Index ZipMaster Component Help=ZipMstr.hlp :Include ZipMstr.cnt Delete the files delphi5.GID, delphi5.FTS and delphi5.FTG. This also works with Delphi 3 and 4 (just substitute the "5" above with your version number). If you have Delphi 2 and want to integrate the help file, you can build a .kwf file. The sources are available for download: * Help source files (98K) http://www.geocities.com/SiliconValley/Orchard/8607/dz-hlpsrc15.zip http://members.tripod.lycos.nl/Vleghert/ c) Trying the demo ================== Open the project "C:\Delphi\Zip\Demo1\ZipDemo1.dpr" and try to compile it. When I did it, I got the following error: [Fatal Error] mainunit.pas(632): Internal error: C3517 This is a compiler error and I'm reporting it to Borland. I isolated the problem and it apparently occurs when optimizations are on (the default) and you explicitly cast an Int64 object property (not a constant or variable) to Int64. It might not occur in your version/build of Delphi, but if it does, there would be two solutions. 1) Turn off optimizations around the ZipMaster1Progress procedure: {$OPTIMIZATION OFF} procedure TMainform.ZipMaster1Progress(Sender: TObject... ... end; {$OPTIMIZATION ON} 2) Or (better) remove the unnecessary Int64 castings: // Step := Integer(Int64(TotalProgress1) * Int64(10000) // div Int64(TotalSize1)); Step := Integer(TotalProgress1 * 10000 div TotalSize1); // Step := Integer(Int64(TotalProgress2) * Int64(10000) // div Int64(TotalSize2)); Step := Integer(TotalProgress2 * 10000 div TotalSize2); Now run the program and click the "Open Zip" button. Select a ZIP file and click "Open". Now what? If you get an EConvertError exception, don't worry: it's not a bug, it's a feature! ;) This time it's true, because TSortGrid uses exceptions to determine the column data type to perform the sort. So, just click OK and let the app keep running (press F9). You'll have to do it three times. If you don't want to see these errors in the future, go to Tools / Debugger Options / Language Exceptions and unmark the checkbox "Stop on Delphi Exceptions" (in previous versions of Delphi it was named "Break on Exceptions" or something like it, and it was located somewhere else...). d) How does it work? ==================== All the work is done by the DLLs, and the TZipMaster component provides a nice programming interface to work with these DLLs, so we don't have to call the APIs directly, relieving us from a lot of the details. The demo application is quite complete and shows all the basic functionality of the TZipMaster component. You can take a look at the code and use the integrated help file to learn more about the use of this component. To help you understand it better we decided to build an alternative demo application, which will be very simple, thinking of providing you a quick start on how to add minimal Zip management capabilities to your application (for back-up purposes, for example), rather than building a compression utility (like WinZip or Power Archiver). To begin, we select New Application from the File menu. Then we edit the program file and we add a resource directive ($) to load the messages (they are available in many languages): program Project1; uses Forms, Unit1 in 'Unit1.pas' {Form1}; {$R *.RES} {$R ZipMsgUS.RES} // Load the English messages begin Application.Initialize; Application.CreateForm(TForm1, Form1); Application.Run; end. Notice that this will only affect messages generated by the component, not by the DLLs (which will be in English). Now we add a TZipMaster component onto the form and we name it Zip to give it a shorter name. Before we start the real work, we'll load the DLLs in memory when the form is created, and we'll unload them when the form is closed. It isn't necessary to do this because TZipMaster handles this automatically, loading and unloading the libraries as needed, but this can mean a performance penalty (it takes time), so we decided to do it on our own: procedure TForm1.FormCreate(Sender: TObject); begin Zip.Load_Zip_Dll; Zip.Load_Unz_Dll; end; procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction); begin Zip.Unload_Zip_Dll; Zip.Unload_Unz_Dll; end; The libraries take some memory when they are loaded, so this is not necessarily the best approach either, but it's better than loading and downloading them every now and then. The problem now is that loading the form would take more time, so perhaps the best approach could be loading the DLLs the first time they are used and unloading them when you stop using them (for example when the form closes), but we leave this up to you. :-) 1) Creating a new archive ------------------------- To show how to create a new Zip file we place a button on the form and we name it CreateZip, and in its Click event we write: procedure TForm1.CreateZipClick(Sender: TObject); const ZipArch: string = 'C:\Temp\Test.zip'; begin if FileExists(ZipArch) then if MessageDlg('"' + ZipArch + '" already exists. Overwrite?', mtConfirmation, [mbYes, mbNo], 0) = mrYes then DeleteFile(ZipArch) else exit; Zip.ZipFilename := ZipArch; if Zip.ZipFilename = '' then begin ShowMessage('Could not create "' + ZipArch + '"!'); exit; end; Zip.AddOptions := []; Zip.FSpecArgs.Add('Project*.*'); try Zip.Add; ShowMessage('Zip archive successfully created!'); except ShowMessage('Add failed!'); end; end; First we asked if the archive already exists, and if so we ask for confirmation to overwrite it. In the affirmative case we delete the existing archive, so when we later add files to the archive, it will be automatically created. The Add method is the one that does all the job, but before we can invoke it we have to do some preparations: a) Set the Zip file name in the ZipFilename property b) Set the options to add the files (for example we can recurse subdirectories, encrypt the files and other stuff). c) Set the files that will be added in the FSpecArgs property (a TStringList object). 2) Adding files to an archive ----------------------------- We have just seen how to add files, but here goes another example. First we place a new button on the form and we name it AddToZip, and in its Click event we write: procedure TForm1.AddToZipClick(Sender: TObject); const ZipArch: string = 'C:\Temp\Test.zip'; begin Zip.ZipFilename := ZipArch; if Zip.ZipFilename = '' then begin ShowMessage('Could not open "' + ZipArch + '"!'); exit; end; Zip.AddOptions := [AddUpdate]; Zip.FSpecArgs.Add('*.d*'); Zip.FSpecArgs.Add('Unit1.pas'); try Zip.Add; ShowMessage('Files added!'); except ShowMessage('Add failed!'); end; end; This example is similar to the previous one, except that we used the AddUpdate option that tells the Add method that if the files we are adding already exist in the archive, they shouldn't be replaced unless they are newer, but files that don't exist in the archive will be added. AddFreshen is like AddUpdate, but doesn't add new files to the archive. The 'standard' Add (if no option is set) will add or replace files unconditionally. AddMove is like the standard Add, but deletes the disk files afterwards. 3) Adding files to an archive in multiple volumes ------------------------------------------------- To span the archive (divide it in multiple parts named volumes), simply include AddDiskSpan in the AddOptions property. To try the following example, add a button named Span to the form and generate its Click event: procedure TForm1.SpanClick(Sender: TObject); const ZipArch: string = 'C:\Temp\SpanTest.zip'; begin Zip.ZipFilename := ZipArch; if Zip.ZipFilename = '' then begin ShowMessage('Could not open "' + ZipArch + '"!'); exit; end; Zip.AddOptions := [AddDiskSpan]; Zip.KeepFreeOnDisk1 := 10000; Zip.MaxVolumeSize := 100000; Zip.FSpecArgs.Add('*.*'); try Zip.Add; ShowMessage('Files added!'); except ShowMessage('Add failed!'); end; end; When spanning the archive in multiple disks, set MaxVolumeSize to 0 and the size of the diskette will be detected automatically. Setting this property to another value will force the parts of the archive (volumes) to be no larger than the value you specify (in bytes). This is useful when spanning the archive in the hard disk. Use KeepFreeOnDisk1 to set the number of bytes to be left free in the first volume. In the above example, the volume size is 100,000 bytes and we requested 10,000 bytes free in the first volume, so the size of the first volume will not exceed the 90,000 bytes. 4) Deleting files from an archive --------------------------------- To delete a file or set of files from an archive we can use the Delete method. To see an example, add a button named DeleteFromZip to the form and generate its Click event: procedure TForm1.DeleteFromZipClick(Sender: TObject); const ZipArch: string = 'C:\Temp\Test.zip'; begin Zip.ZipFilename := ZipArch; if Zip.ZipFilename = '' then begin ShowMessage('Could not open "' + ZipArch + '"!'); exit; end; Zip.FSpecArgs.Add('*.c*'); Zip.FSpecArgsExcl.Add('*.cfg'); try Zip.Delete; ShowMessage('Files deleted!'); except ShowMessage('Delete failed!'); end; end; In this example we introduced the FSpecArgsExcl property, a StringList that contains the names of the files to exclude from the operation (in this case Delete). In the above example, all files matching the pattern *.c* but not *.cfg will be deleted from the archive. 5) Extracting files from an archive ----------------------------------- This operation is performed by the Extract method. To see an example, add a button named ExtractFromZip to the form and generate its Click event: procedure TForm1.ExtractFromZipClick(Sender: TObject); const ZipArch: string = 'C:\Temp\Test.zip'; var CurrentDir: string; begin Zip.ZipFilename := ZipArch; if Zip.ZipFilename = '' then begin ShowMessage('Could not open "' + ZipArch + '"!'); exit; end; CurrentDir := GetCurrentDir; ChDir(ExtractFilePath(ZipArch)); Zip.ExtrOptions := [ExtrOverWrite, ExtrUpdate]; try Zip.Extract; ShowMessage('Files extracted!'); except ShowMessage('Extract failed!'); end; ChDir(CurrentDir); end; The destination folder is the current working directory, so we should change it (with the ChDir procedure) if we want it to be another one. Previously we save the current directory so we can restore it later. In the example, we used the folder where the Zip archive is located ('C:\Temp'). Since we didn't specify the files to process in FSpecArgs, all files in the archive will be extracted. You can specify some extracting options in the ExtrOptions property. The default extract method will only extract files if they don't exist in the disk. If you want to overwrite existing files, use the ExtrOverWrite option (equivalent to the standard Add). You can combine it with ExtrUpdate (equivalent to AddUpdate) or ExtrFreshen (equivalent to AddFreshen). You can use the option ExtrDirNames to recreate the relative pathnames stored in the archive (paths are stored using the AddDirNames option with the Add method). 6) Testing an archive --------------------- To test the integrity of a Zip archive we use the Extract method with the ExtrTest option and then we check the value of the ErrCode property. To see it working, add a button named TestZip to your form and generate its Click event: procedure TForm1.TestZipClick(Sender: TObject); const ZipArch: string = 'C:\Temp\Test.zip'; begin Zip.ZipFilename := ZipArch; if Zip.ZipFilename = '' then begin ShowMessage('Could not open "' + ZipArch + '"!'); exit; end; Zip.ExtrOptions := [ExtrTest]; try Zip.Extract; if Zip.ErrCode = 0 then ShowMessage('Test successful!') else ShowMessage('Error(s) found in Zip file'); except ShowMessage('Test failed!'); end; end; 7) Intercepting the messages ---------------------------- Add a Memo control to your form and generate the Message event of the Zip component: procedure TForm1.ZipMessage(Sender: TObject; ErrCode: Integer; Message: String); begin if ErrCode = 0 then Memo1.Lines.Add(Message) else Memo1.Lines.Add('Error #' + IntToStr(ErrCode) + ': ' + Message); end; The Memo will now show the messages sent by the DLL. Try the operations we introduced above to see them. 8) Listing the files stored in the archive ------------------------------------------ The ZipContents property is a TList that holds pointers to ZipDirEntry records that contain detailed information about the files stored in the zip archive. To see an example, add a button named ListFiles to the form and generate its Click event: procedure TForm1.ListFilesClick(Sender: TObject); const ZipArch: string = 'C:\Temp\Test.zip'; var i: integer; f: ^ZipDirEntry; begin Zip.ZipFilename := ZipArch; if Zip.ZipFilename = '' then begin ShowMessage('Could not open "' + ZipArch + '"!'); exit; end; for i := 0 to Zip.Count - 1 do begin f := Zip.ZipContents[i]; Memo1.Lines.Add(Format('%s %.1fK (%.0f%%)', [f.FileName, f.UncompressedSize / 1024, f.CompressedSize / f.UncompressedSize * 100])); end; end; Well, this is as far as we go. The demo application that comes with Delphi Zip is more complete and will show you many features of the TZipMaster component (like encryption and Self-Extracting executables), and you can learn more from the help file. You can download the full source code of the examples presented in this newslettter: http://www.latiumsoftware.com/download/p0005.zip In the next issue we'll use this component in our Find File application to extend the search to zipped files. See you then. ________________________________________________________________________ YOU CAN HELP US We need your help to keep this newsletter going and growing. You can help by referring the newsletter to your colleagues: http://www.latiumsoftware.com/en/pascal/delphi-newsletter.php Or you can help by voting for us in some or all of these rankings to give more visibility to our web site and thus increase the number of subscriptions to this newsletter: http://www.sandbrooksoftware.com/cgi-bin/TopSite2/rankem.cgi?id=latium http://news.optimax.com/delphi/links/links.exe/click?id=70C517ECAE6E http://www.programmingpages.com/?r=latiumsoftwarecomenpascal http://www.top219.org/cgi-bin/vote.cgi?delphi&83 http://top100borland.com/in.php?who=20 http://top200.jazarsoft.com/delphi/rank.php3?id=latium http://213.65.224.200/cgi-bin/toplist.cgi/hits?Id=80 It's just a few seconds for you that REALLY mean a lot to us. ________________________________________________________________________ If you haven't received the full source code examples for this issue, you can get them from http://www.latiumsoftware.com/download/p0005.zip ________________________________________________________________________ This newsletter is provided "AS IS" without warranty of any kind. Its use implies the acceptance of our licensing terms and disclaimer of warranty you can read at http://www.latiumsoftware.com/en/legal.php where you will also find a note about legal trademarks. Articles are copyright of their respective authors and they are reproduced here with their permission. You can redistribute this newsletter as long as you do it in full (including copyright notices), without changes, and gratis. ________________________________________________________________________ Main page: http://www.latiumsoftware.com/en/pascal/delphi-newsletter.php Group home page: http://groups.yahoo.com/group/pascal-newsletter/ Subscribe/join: pascal-newsletter-subscribe@yahoogroups.com Unsubscribe/leave: pascal-newsletter-unsubscribe@yahoogroups.com Problems with your subscription? eds2004 @ latiumsoftware.com ________________________________________________________________________ Latium Software http://www.latiumsoftware.com/en/index.php Copyright (c) 2000 by Ernesto De Spirito. All rights reserved. ________________________________________________________________________ |
The full source code examples of this issue are available for download.
![]() |
Errors? Omissions? Comments? Please contact us!






