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

使用 ICSharpCode.SharpZipLib 的控制台 ZIP 工具

starIconstarIconstarIcon
emptyStarIcon
starIcon
emptyStarIcon

3.60/5 (4投票s)

Nov 30, 2007

5分钟阅读

viewsIcon

75863

downloadIcon

1302

一个使用 SharpZipLib 的示例但可用的程序。

Screenshot - MZip.gif

摘要

我一直在寻找一个程序,用于以差异化方式备份我的文件:能够存储自上次备份以来已修改的文件。为此,有一个好方法:使用文件的最后修改日期。我还想将它们记录在广泛传播的格式中,以便有很大的机会在几年内能够恢复它们。

Zip 格式似乎是此目的的最佳选择。而且我希望该过程完全自动化,以避免浪费时间和可能在保存文件时出错。为此,一个好用的批处理文件似乎是最好的。那么问题就是找到一个能够做到这一点的命令行 zip 工具。

互联网上似乎只有一种这样的免费程序:开源的 Info-ZIP 工具。但是 Info-Zip 存在代码页问题,导致 InfoZip 创建的 zip 文件可以被一些解压器完全读取,但并非所有解压器都可以,当文件名包含扩展字符(如某些欧洲语言使用的字符)时。例如,Windows 内置的 zip 功能在文件名包含扩展字符且 zip 文件是用 Info-Zip 创建时会显示错误的文件名。如果文件名只包含美国标准字符,这并不重要,但如果,例如,它们包含特定的欧洲字符,如 ń、î、é 等……那就很不方便了。

由于没有其他可用工具,我决定自己写一个。网上有几种 zip 库可用。我决定使用 ic#code 的库。它相对简单地工作。
我将此程序作为使用该库的完整示例程序提供给 CodeProject 社区。我希望它能帮助那些想在他们的软件中添加 zip 功能的读者,或者仅仅是出于自己的备份目的而使用该工具的读者。

背景

CodeProject 上还有几篇关于 ic#code zip 库的文章,例如 这篇,它提供了关于 zip 和 unzip 文件的基本视图。

使用该实用工具

该实用程序可以用作传统的 zip 实用程序,但它有一个特殊功能,可以轻松自动创建差异备份文件。当使用常规的 /? 参数启动时,它会显示帮助文本

MZip
Zip archive creating and updating utility.
Syntax:
MZip /zip=Zip file name [/a] [/d=date or file name] [/r|R] [/l] file(s) or
directory(ies) name(s)
/zip=Name of the file to create or update
/a if present and if the zip file exists, its contents is merged with
the new files otherwise, a new zip file is created.
/d=date/time The files are stored to the zip archive if they were modified
after this date/time.
A file name can be given instead of a date. In this case the date/time when
the file was last modified is used as a starting date for storing files.
If a date/time is given, its format depends on the language settings of
the computer and can be any usual format for a date/time such as 1/1/2000 8:00.
If a date such as 10:30 is given it means today at 10:30.
[/l] tells the program only to list the files, not to store them.
/r means to store the relative directory of the files when a directory name
is given, and the absolute path name when a file name is given.
/R means to store the absolute path of the files in any case.
This program is provided on an "AS-IS" basis. You can use it freely but
at your own risks. The author is not liable for any direct
or indirect damage caused by the program.

特定的是 /d= 可选参数。此参数可以包含日期/时间字符串或文件名。如果包含日期,则表示程序必须记录所选文件中在此日期之后修改的文件。如果包含文件名,则表示程序必须采用此文件的最后修改日期。这使得创建一个非常简单的批处理文件来创建差异备份成为可能

MZip /zip=DifferentialBackup.zip /d=MyTimeStamp.txt /R c:\MyDirectory
echo My time stamp >MyTimeStamp.txt

这样的批处理文件将创建一个包含自上次启动以来修改过的文件的存档。

一个稍微复杂且更有趣的批处理文件是

date /t >%temp%\MyDate.txt
set /p MyDate= <%temp%\MyDate.txt
set MyDate=%MyDate: =%
set MyDate=%MyDate:/=.%
if exist %temp%\MyDate.txt del %temp%\MyDate.txt
MZip /zip=Backup.%MyDate%.zip /d=MyTimeStamp.txt /R c:\MyDirectory
echo My time stamp >MyTimeStamp.txt

此批处理文件根据日期为备份文件命名。您可以例如将生成的文件直接刻录到 CD 或 DVD 以进行有效备份,并每周执行一次:每个每周文件都会有不同的名称。

万一发生灾难,可以通过按时间顺序解压缩文件来恢复文件。

因为 MZip 创建的 zip 文件与 Windows zip 功能兼容,所以当您需要从命令行 zip 文件(主要是如果您的语言使用扩展字符集)时,它也是一个不错的选择。

Using the Code

代码的主要部分旨在创建要压缩的文件列表并将其存储到 SortedList 集合中。

这里有趣的一点是 AnalyseCommande 类,这是一个可重用的类,以相对灵活的方式解析命令行。

同样有趣的是使用 SharpZipLib 库来读取或写入 zip 文件。要读取文件,您首先需要创建一个 FileStream 对象。然后,从该对象创建 ZipInputSream 对象,要读取存档中的文件,则创建一个对应于您要读取的文件的 ZipEntry 对象。在此程序中,它们按顺序一个接一个地选择。然后简单地像普通流一样读取数据,使用 ZipInputStream 对象的 Read 方法。就是这样,它非常简单和简短,如下面的程序部分所示

FlotEntree=new FileStream(NomFichierZip,FileMode.Open,FileAccess.Read,
    FileShare.None);
FichierZipEntree=new ZipInputStream(FlotEntree);
//then we access all the entries of the existing archive

for(MonEntreeLue=FichierZipEntree.GetNextEntry();
    MonEntreeLue!=null;MonEntreeLue=FichierZipEntree.GetNextEntry())
{
    //here the entry has to be copied to the new archive, this is done by

    //creating a "ZipEntry" object, then to feed the zip flow with the

    //data of the file 

    //Creating the zip entry

    MonEntree=new ZipEntry(ZipEntry.CleanName(MonEntreeLue.Name));    
    //setting the necessary parameters from the original entry, here, the date

    MonEntree.DateTime=MonEntreeLue.DateTime;
    MonEntree.Size=MonEntreeLue.Size;            //... and the size

    //adding the new entry to the zip file

    FichierZipSortie.PutNextEntry(MonEntree);    
    for(LongueurRestante=(int)FichierZipEntree.Length;LongueurRestante!=0;)
    {
        //this loop copies the file contents from the original archive

        //to the new one by unzipping from the old one then zipping to

        //the new one

        LongueurLue=FichierZipEntree.Read(BufferTransfert,0,
            LongueurRestante<1024*1024?LongueurRestante:1024*1024);
        //unzipping a block

        //no byte read, we are at the end of the block

        if(LongueurLue==0)break;    
        //writing the block

        FichierZipSortie.Write(BufferTransfert,0,LongueurLue);    
        LongueurRestante-=LongueurLue;    //Computing the length to be read

    }
}

此程序比简单地读取文件要复杂一些,因为它将读取的数据写入新的 zip 存档。

写入 zip 文件也同样简单,但它使用了 ZipOutpuStream 类。

整个程序是用 SharpDevelop IDE 创建的,这是一个有趣的 .NET 开源 IDE,sln 项目可以与该 IDE 一起使用。它也应该可以在 Microsoft 的工具中使用。MZip.exe 程序是独立的,不需要任何 DLL 即可工作。这要归功于使用 Microsoft 的 ILMerge 工具来合并原始 exe 文件(由编译器创建)和 DLL。

关注点

编程此工具并不复杂。但是 SharpZipLib 提供了许多类,这些类有时看起来是等效的,并且要弄清楚所有这些类并不容易。该程序通过两个主要类 ZipInputStreamZipOutputStream 展示了读取或创建 zip 文件的一种有效方法。

我的目的是帮助任何想要创建 zip 功能的开发人员。使用我的程序中所示的方式使用此库既简单又快捷,并且能获得出色的结果。

© . All rights reserved.