65.9K
CodeProject 正在变化。 阅读更多。
Home

打造你自己的压缩工具 1 / 3

starIconstarIconstarIcon
emptyStarIcon
starIcon
emptyStarIcon

3.29/5 (6投票s)

2008年12月5日

LGPL3

7分钟阅读

viewsIcon

37967

downloadIcon

929

本文介绍如何使用 CAKE3 执行列表、提取、添加和操作压缩文件。

引言

很多年前,当我开始学习如何开发软件时,zip软件是我开发的最早的产品之一,我使用 DelZip 的演示版开发了我的第一个原型。

我发现开发这样一个产品是学习如何编程窗口程序的绝佳方式。要构建最基本的 zip 软件,您必须学会如何使用现有框架做很多事情,例如用户界面、IO 处理、Shell、Win32 API。一旦完成了基础知识,您就可以应用您刚学到的所有新功能,例如备份支持、CD 刻录机支持。

开发 zip 软件有很多方法,但如果您想开发一个支持多种压缩文件类型的软件,您要么必须购买昂贵的商业解决方案,要么编写大量代码来支持每种压缩文件类型。我选择自己编写代码,并且自 2001 年以来就发布了它们(名为 CAKE),源代码是在 LGPL 许可下发布的,您可以自由使用它来开发自己的压缩工具。

由于 CAKE3 缺乏文档,我写了这个教程来解释如何使用 CAKE3 编写最基本的压缩工具。

本教程包含 3 部分

  1. 压缩操作(本文)
  2. 文件列表、目录树和拖放
  3. 多线程支持

CAKE (Common Archiver Kit Experiment) 历史

早在 2001 年首次开发时,市面上有许多免费的压缩文件支持组件,每个组件都支持几种压缩格式,因此 CAKE 的编写是为了整合这些组件以支持更广泛的压缩文件类型。由于它是用 Delphi 开发的,组件的用户在安装 CAKE 之前必须安装大约 9 个组件。

(例如:CAKE2 <-----> Cmarc<-----> 7zip-32.dll

2006 年,CAKE 被移植到 dotNet 环境(CAKE3.NET),压缩文件处理的代码被重写,不再需要中间层,并且所有外部 w32 DLL 都被直接调用。为了便于移植,一些 Delphi 命令(AppendSlashExtractFileName)也被移植过来,全部包含在 Cake3.Utils 类中。在此版本中,还可以使用相对路径向压缩文件中添加文件。

(例如:CAKE3 <-----> 7-zip32.dll

Cake 结构

  • Cake3 (Cake3.dll)
    • Cakdir3:主类,大多数压缩操作在此进行
    • ContentList:一个包含内容类型的列表(您可以将其读取为 List<ContentType>
    • ContentType:表示压缩文件中的一个文件
    • Defines:杂项结构的定义
      • 添加/删除/提取/SFX选项
    • Queue:用于支持多线程,将在后续文章中解释
      • CakdirThreadQueue
      • CakdirWorkItem
      • ThreadQueueMonitor
    • Utils:所有可用工具
    • {CakArchiver,连接其他 dotNet 组件或 DLL}
      • Ace
      • Cmarc
      • IconLib
      • InstallBuild
      • Rar
      • SharpZipLib
      • Sqx
      • WcxPlugins

打造你自己的压缩工具 1

请注意,在附带的演示程序中,所有压缩文件处理例程都放在与 UI 分开的方法中,这样可以使程序更容易修改。

此演示需要 VS2008,如果您想使用 SharpDevelop,请重新创建项目然后添加源代码。

打开一个压缩文件

1) Cakdir3 cakdir = new Cakdir3(archiveName); 
  • 很简单,只需注意,每次打开新压缩文件时都必须创建一个新的 Cakdir3 实例。

    如果压缩文件不存在,当您向其中添加文件时(见下文)它会创建它。

列出压缩文件内容(到名为 lvFileList 的 listview)

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) }
  • 第 2 行请求 cakdir3 执行列出内容的操作,您也可以指定其他掩码(请记住只支持 *,不支持 ?)。
  • 第 3 行,cakdir.Archive_Contents 是一个 ContentList,包含零个或多个 ContentTypes
  • 第 5 行,为每个条目创建一个新的 ListViewItemUtils.SizeInK 将一个 int 转换为 kb 字符串(例如,74550000 ---> "745.50 kb")

列表现在可以工作了,但是没有图标看起来不吸引人,所以我们现在添加图标支持。

列出带图标的压缩文件内容

您必须在 MainForm 中创建一个名为(imageS,表示小图标)的 ImageList,并将其链接到 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);  
  • 第 5.1 行指定了一个 imagekey,它基于文件扩展名(Utils.ExtractFileExt extract ext 从一个 string 中提取扩展名)
  • 第 5.2 行和 5.3 行,如果图像列表不包含 imagekey,它将检索指定扩展名的图标并将其添加到图像列表中。

    Utils.GetSmallFileIcon() 使用 W32 API(SHGetFileInfo)来检索图标。您也可以找到 Utils.GetLargeFileIcon。)

提取压缩文件中的文件

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();
  • 第 2 行,您可以使用 CanExtract 来查看是否可以从指定的压缩文件中提取文件,还有一个 CanList / CanAdd

    如果您想在不打开压缩文件的情况下进行检查,可以使用(Cakdir3.GetArchiveType(".zip").CanExtract)。

  • 第 3-6 行,所有与提取相关的选项都位于 ExtractOptions 中。
    • archiveName:压缩文件名,通常您不必修改它。
    • allowFolder:是否使用文件夹信息。
    • dialogless:一些压缩文件 DLL 在执行时会显示进度对话框,启用此项将禁用 DLL。
    • extractFolder:指定提取位置。
    • extractItem:指定要提取的项目。
    • extractOverwrite:是否覆盖现有文件。
    • password:指定密码。
    • ResetExtractItem():将 extractItem 设置为 "*"。
  • 第 7 行将在提取成功时返回 true

    或者,您也可以调用以下方法。

3) cakdir.Extract(filter, extractTo, useFolder, allowOverwrite); 

以下方法可以递归提取文件(例如,“outer.zip\inner.zip\core.zip”)

3) Utils.ExtractArchiveRecrusive(archiveName, extrOptions); 

向压缩文件添加文件

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("*");
  • 第 3-4 行,所有与添加相关的选项都位于 AddOptions 中。
    • addCompressLevel:0..9,cake 尚不支持单独的压缩方法。
    • addFile:要添加的文件。
    • addFolder:如何存储文件夹信息,从下面的 folderMode 中选择一个。
      folderMode 描述

      如果添加 "c:\ temp \ test \ file.txt" 并将 baseFolder 设置为 "c:\temp"

      full 存储完整的文件夹信息。 \ temp \ test \ file.txt
      none 存储不包含任何文件夹信息。 file.txt
      relative 存储相对于 baseFolder 的文件夹信息。 \ test \ file.txt
    • addMode:如何添加文件,从下面的 updateMode 中选择一个。
      updateMode 描述
      加法 将所有指定的文件添加到压缩文件中。
      刷新 更新压缩文件中较旧的文件,并添加新文件。
      update 更新压缩文件中比选定磁盘文件旧的指定文件。
      synchronize 如果较新则替换,即使未在压缩文件中找到也要添加,如果未在磁盘上找到则删除。
    • archiveName:压缩文件名,通常您不必修改它。
    • baseFolder:当 addFolder = relative 时的基准文件夹。
    • dialogless:一些压缩文件 DLL 在执行时会显示进度对话框,启用此项将禁用 DLL。
    • password:指定密码。
    • defaultOptions():恢复到默认选项。
  • 第 5 行将在添加成功时返回 true

    请注意,所有操作(添加/提取/删除)都不是多线程的。

  • 第 6 行强制 cakdir3 再次执行列出内容的操作。

从压缩文件中删除文件

1) if (cakdir == null) return;
2) if (!cakdir.CanAdd) return;
3) cakdir.DeleteOptions.deleteFile = deleteFile;
4) cakdir.Delete();
5) cakdir.List("*"); 
  • 第 3 行,所有与删除相关的选项都位于 DeleteOptions 中。
    • archiveName:压缩文件名,通常您不必修改它。
    • deleteFile:要删除的文件。
  • 第 4 行将在添加成功时返回 true
  • 第 5 行强制 cakdir3 再次执行列出内容的操作。

处理进度消息

让用户知道正在进行什么工作。

1) cakdir.OnMessage += new MessageEventHandler(ProgressScreen_Message);
.....
2) void ProgressScreen_Message(object sender, MessageEventArgs e)
3) { tbMessage.Text += e.Message + Environment.NewLine; }
  • 第 3 行会将消息追加到 textboxtbMessage)中。

您也可以使用进度条显示进度。

1) cakdir.OnProgress += new MessageEventHandler(ProgressScreen_Progress);
.....
2) void ProgressScreen_Progress(object sender, MessageEventArgs e)
3) { pBar.Value = e.Percent; }
  • 第 3 行将设置进度条(pBar)的百分比,其他属性在 MessageEventArgs 中。
    • Percent:完成百分比(1..100)。
    • Filename:正在处理的文件。

请注意,进度条并非对所有压缩文件都完全有效。

Cakdir3 中包含的其他事件

  • OnStartWorking / OnStopWorking:开始和完成时的信号。
  • OnError:发生错误时的信号。
  • OnOverwrite - 当提取时 extractOverwrite 设置为 false,它会在文件已存在时发出信号(如果未覆盖,则使用内部覆盖处理程序)。
  • OnPassword - 需要密码时发出信号。
  • OnItemList - 通常供内部使用,当 Cakdir.InternalList 开启时,通过此事件列出,而不是通过 Archive_Contents

完成此部分后,您应该知道如何使用 Cake3 执行大多数压缩操作。下一篇文章将介绍如何改进用户界面,实现虚拟文件列表、目录树和拖放支持。

参考文献

历史

  • 2008-05-12 - 首次提交至 CodeProject
© . All rights reserved.