Home‎ > ‎Articles‎ > ‎

Craft Your Own Archiver 1 / 3

This article describe how to perform list, extract, add and operations to archives using CAKE3.

Many years ago, when I start learning how to develop software, zippware is one of my first products I developed, I developed my first prototype using a demo of DelZip.

I found that developing such product is a good way to learn how to program window programs.  To build the most basic zippware, you have to learn how to do many things using the existing framework, like User Interface, IO handling, Shell, Win32 API.  Once you completed the basics, you can apply most new features that you just learned, like backup support, CD burner support.

There are many ways to develop an zippware, but if you want to develop one that support a very wide range of archive types, you will either have to purchase an expensive commercial solutions, or write a lot of code to support each archive types.  I choosed to write my own code, and I release them since 2001 (named CAKE), the source code is under LGPL license, you are free to use it to develop your own archiver.

Because CAKE3 is lack of documentation, I write this tutorial to explain how to write the most basic archiver using CAKE3.

This tutorial include 3 parts,
  1. Archive Operations
  2. File List, Directory Tree and Drag n Drop
  3. Threading support

CAKE (Common Archiver Kit Experiment) History

Back in around 2001, when first developed, there was many freeware archive support components, each support a few archive formats, so CAKE is written to combine these components to support wider range of archives.  Because it was developed under Delphi, users of the component have to install around 9 components before installing CAKE.
(e.g. CAKE2 <-----> Cmarc<-----> 7zip-32.dll)

In 2006, CAKE is being ported to dotNet environment (CAKE3.NET), the code of archive handling is rewritten, no longer require the middle layer, and all external w32 dll is called directly.  To make the port easier, some Delphi commands (AppendSlash, ExtractFileName) are ported as well, all under Cake3.Utils class.  Add files to archive using relative path is also possible in this version.
(e.g. CAKE3 <-----> 7-zip32.dll)

CAKE Structure
  • Cake3 (Cake3.dll)
    • Cakdir3
    • ContentList : A list contain Content Type. (you can read it as List<ContentType>)
    • ContentType : Represent a file in an archive.
    • Defines : Definition of misc structures
      • Add / Delete / Extract / SFXOptions
    • Queue : For support threading, will be explained in future articles
      • CakdirThreadQueue
      • CakdirWorkItem
      • ThreadQueueMonitor
    • Utils : All tools available
    • {CakArchiver}
      • Ace
      • Cmarc
      • IconLib
      • InstallBuild
      • Rar
      • SharpZipLib
      • Sqx
      • WcxPlugins

Craft Your Own Archiver 1

Please noted that in the attached demo, all archive handling routines are placed in separate methods (from UI), this will make the program easier to modify.
This demo requires VS2008, if you want to use SharpDevelop please recreate the project then add the source again.

To Open an Archive :
1) Cakdir3 cakdir = new Cakdir3(archiveName);
  • quite simple, just noted that you have to create a new instance of Cakdir3 everytime you open a new archive.
    if the archive is not exists, it will create it when you add file(s) to archive (see below).

To List Archive Contents (to a listview named lvFileList) :
1) if (cakdir == null) return;
2) cakdir.List("*");
3) foreach (ContentType ct in cakdir.Archive_Contents)
4) {
5) ListViewItem item = new ListViewItem(new string[] {ct.fileName, Utils.SizeInK(ct.fileSize) });
6) lvFileList.Items.Add(item);
7) }
  • Line 2 request cakdir3 to perform list content, you can specify other mask as well (keep in mind only * is supported, ? is not supported).
  • Line 3, cakdir.Archive_Contents is a ContentList containing zero or more ContentTypes.
  • Line 5 create a new ListViewItem for each entry, Utils.SizeInK convert a int to kb string, (e.g. 74550000 ---> "745.50 kb")

The listing is working now, however it looks unattractive without icons, so we shall add Icon support now.

To List Archive Contents with Icons :
You have to create a ImageList named (imageS, means small images) in MainForm, hook it to lvFileList.SmallIcons.
5)    ListViewItem item = new ListViewItem(new string[] {ct.fileName, Utils.SizeInK(ct.fileSize) });
5.1)  item.ImageKey = Utils.ExtractFileExt(ct.fileName).ToLower();
5.2)  if (!imageS.Images.ContainsKey(item.ImageKey))
5.3)  imageS.Images.Add(item.ImageKey, Utils.GetSmallFileIcon(ct.fileName));
6) lvFileList.Items.Add(item);
  • Line5.1 specify a imagekey, which is based on the extension of file. (Utils.ExtractFileExt extract ext from a string)
  • Line5.2 and 5.3, if image list does not contain the imagekey, it will retrive a icon for the specified extension and add it to image list.
    (Utils.GetSmallFileIcon() uses W32 api (SHGetFileInfo) to retrive icon.  You can find Utils.GetLargeFileIcon as well)
To Extract files from archive :
1) if (cakdir == null) return;
2) if (!cakdir.CanExtract) return;
3) cakdir.ExtractOptions.extractItem = new string[] { "*" };
4) cakdir.ExtractOptions.extractFolder = @"c:\temp";
5) cakdir.ExtractOptions.allowFolder = true;
6) cakdir.ExtractOptions.extractOverwrite = true;
7) bool success = cakdir.Extract();
  • Line 2, you can use CanExtract to see if files can be extracted from specified archive, there's also CanList / CanAdd,
    if you want to check if archive without opening it, use ( Cakdir3.GetArchiveType(".zip").CanExtract ) instead.
  • Line 3-6, all extract related options is located in ExtractOptions
    • archiveName : name of archive, you dont have to touch this normally.
    • allowFolder : whether use folder information
    • dialogless : some archiver dll do show progress dialog when executing, enable this will disable the dlls.
    • extractFolder : specify where to extract.
    • extractItem : specify item to extract
    • extractOverwrite : whether to overwrite existing files.
    • password : specify password
    • ResetExtractItem() : set extractItem to "*"
  • Line 7 will return true if extract is success,
    alternatively you can call the following method instead.
3) cakdir.Extract(filter, extractTo, useFolder, allowOverwrite);
The following method can extract file recursively (e.g. "outer.zip\inner.zip\core.zip")
3) Utils.ExtractArchiveRecrusive(archiveName, extrOptions);
To Add files to archive :
1) if (cakdir == null) return;
2) if (!cakdir.CanAdd) return;
3) cakdir.AddOptions.addFile = addFile;
4) cakdir.AddOptions.addFolder = AddOptions.folderMode.full;
5) bool success = cakdir.Add();
6) cakdir.List("*");
  • Line 3-4, all add related options is located in AddOptions
    • addCompressLevel : 0..9, cake do not have individual compression method support yet.
    • addFile : file to add.
    • addFolder : how to store folder information, select one of folderMode below :
      if add "c:\ temp \ test \ file.txt" and
      set baseFolder as "c:\temp"
       fullStore full folder information. \ temp \ test \ file.txt
       noneStore no folder information. file.txt
       relativeStore folder information relative to  baseFolder.
       \ test \ file.txt
    • addMode : how to add file, select one of the updateMode below :
       addAdd all specified files to the archive.
       refreshUpdate older files in the archive and add files that are new to the archive.
       updateUpdate specified files in the archive that are older than the selected disk files.
       synchronizeReplace if newer, add even if not present in archive, delete if not present in disk.
    • archiveName : name of archive, you dont have to touch this normally.
    • baseFolder : base folder if addFolder = relative.
    • dialogless : some archiver dll do show progress dialog when executing, enable this will disable the dlls.
    • password : specify password
    • defaultOptions() : revert back to default options.
  • Line 5 will return true if add is success,
    please noted that all operation (Add / Extract / Delete) is not threaded.
  • Line 6 force cakdir3 to perform list content again.

To Delete files from archive :
1) if (cakdir == null) return;
2) if (!cakdir.CanAdd) return;
3) cakdir.DeleteOptions.deleteFile = deleteFile;
4) cakdir.Delete();
5) cakdir.List("*");
  • Line 3, all delete related options is located in DeleteOptions
    • archiveName : name of archive, you dont have to touch this normally.
    • deleteFile : file to delete.
  • Line 4 will return true if add is success,
  • Line 5 force cakdir3 to perform list content again.
Handling progress message :
Let user know whats working on.
1) cakdir.OnMessage += new MessageEventHandler(ProgressScreen_Message);
2) void ProgressScreen_Message(object sender, MessageEventArgs e)
3) { tbMessage.Text += e.Message + Environment.NewLine; }
  • Line 3 will append the message to a textbox (tbMessage)

You can show display progress using a progress bar too
1) cakdir.OnProgress += new MessageEventHandler(ProgressScreen_Progress);
2) void ProgressScreen_Progress(object sender, MessageEventArgs e)
3) { pBar.Value = e.Percent; }
  • Line 3 will set the percentage of progress bar (pBar), other properties in MessageEventArgs
    • Percent : Percentage completed (1..100)
    • Filename : File processing
please noted that progress bar is not completely working for all archiver yet.

Other events included in Cakdir3
  • OnStartWorking / OnStopWorking : signal when start and finish.
  • OnError : signal when error occured.
  • OnOverwrite - when extract with extractOverwrite set to false, it signal when a file already exists. (if not overrided, internal overwrite handler is used)
  • OnPassword - signal when password required.
  • OnItemList - usually for internal use, when Cakdir.InternalList is on, list via this event instead of Archive_Contents.

When you completed this part, you should know how to use Cake3 to do most archive operations.  The next article will describe how to improve the User Interface, implement virtual file list, directory tree and drag and drop support.



This article, along with any associated source code and files, is licensed under The GNU Lesser General Public License

Site Meter
Leung Yat Chun Joseph,
Sep 16, 2008, 5:08 AM
Leung Yat Chun Joseph,
Sep 27, 2008, 1:09 AM
Leung Yat Chun Joseph,
Sep 20, 2008, 4:55 AM