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

#zlib - 修改存档

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.35/5 (9投票s)

2006 年 4 月 27 日

3分钟阅读

viewsIcon

79817

downloadIcon

819

一种无需完全解压即可修改 Zip 存档的方法。

Demo app

引言

本文简要介绍了一些类,这些类使您可以修改存档而无需完全解压它。 我解决问题的方式并不是很完美,但它确实有效。 我混合使用了现有的 C# 包装代码 zlib(以及 minizip)和我自己的一些代码。 更好的方法是为 libzip 编写一个包装类。 并且,最好的方法可能是增强 SharpZipLib,以便它可以修改存档。 因此,请随意处理它 ;-)。

另请注意,这些类不支持增强的设置,例如压缩级别或存档注释,因为我不需要它们。 但是您可以轻松添加这些功能。

背景

每个需要在 C# 中进行压缩/解压缩的人很可能会使用来自 IC#Code 的 SharpZipLib。 我也这样做了。 到目前为止。 我一直在使用该库来压缩我的程序生成的数据。 幸运的是,输出都是相同的类型,因此我可以将其保存在同一文件中。 但是现在我有不同类型的数据,这些数据属于程序的不同部分,因此将数据拆分为文件是实现此目的的好方法。 我想在内存中修改这个存档,因为完全解压它相当难看。 我搜索了一段时间,只找到了 Gerry Shaws 的一个旧的 C# 包装类。 我知道 SharpZipLib 对我来说不是一个解决方案,所以我下载了它并尝试使其工作。 它里面有一些错误,导致了一些奇怪的行为,在我用正常的 C# 代码替换了所有不安全的部分后,这些行为消失了(你现在必须这样做,Gerry 的代码有点奇怪;)。 此外,我根据我的需要对代码进行了大量调整。 我用 ZipStreamZipArchive 类替换了他难以处理的 ZipReaderZipWriter 类,这使得读取和写入存档的方式更加容易。 它在某种程度上隐藏了非托管 zlib 函数的丑陋之处:P。

使用代码

我已经(希望)使修改存档变得非常简单。 您只需要实例化一个 Archive 类,该类使您可以访问流数组。

// Don't forget to add this two lines
using System.IO;
using OrganicBit.Zip;

ZipArchive Archive = new ZipArchive("test.zip", FileAccess.ReadWrite);

byte[] Data = new byte[Archive["test.txt"].Length];

Archive["test.txt"].Read(Data,0,Data.Length);

Console.WriteLine("Contents of 'test.txt'\n"+ 
        System.Text.Encoding.Default.GetString(Data));
Console.WriteLine("Contents of the new file:");

Data = System.Text.Encoding.Default.GetBytes(Console.ReadLine());

Archive["test.txt"].Write(Data,0,Data.Length);

Archive.Close();

请注意,即使test.zip不存在,您也必须使用FileAccess.Write打开它,然后会自动创建一个新的存档。 另外,当您写入现有存档并且该文件尚未在存档中时,将创建该文件。

要查看存档中的内容,您可以简单地枚举您的实例

// Besides the Name, a ZipEntry
// instance also offers lots of other information
foreach(ZipEntry entry in Archive) 
  Console.WriteLine(entry.Name);

您还可以检查文件是否存在,或者删除一些文件

if(Archive.Contains("test.txt"))
  Console.WriteLine("File test.txt is there");

// Archive.Delete() deletes the whole archive
// when it doesn't contain any other files
bool success = Archive.DeleteFile("test.txt");
if(success) 
  Console.WriteLine("File has been deleted");
else Console.WriteLine("File is not in archive");

限制

  • 只能创建/修改.zip存档。
  • 硬编码的设置(注释/压缩级别/等)。
  • 没有加密。
  • 很可能限制为 2 GB 存档甚至更少。

关注点

zlib 与 minizip 不可爱的部分是,您不能同时打开存档进行读取和写入。 我在我的类中隐藏了这一事实,并且仅公开了 ReadWrite 函数。 但是,在幕后,每当您从读取函数切换到写入函数或反之亦然时,我的类都会关闭并重新打开存档。 其次,zlib/minizip 不支持任何修改和/或删除文件的可能性。 但是在 minizip 主页上有一个链接到 小型示例,其中包含 Ivan A. Krestinin 编写的有关如何删除文件的 C++ 代码。 我只是将该函数转换为 C#,并将其添加到我的 ZipArchive 类中。 因此,每当您写入现有条目时,旧文件都会首先被删除!

致谢

...去以下人员

  • zlibminizip 开发人员。
  • Gerry Shaw 的 C# 包装器 for zlib,我的工作是基于此。
  • Ivan A. Krestinin,感谢他关于如何从存档中删除文件的示例。

历史

  • 2006-04-08
    • 插入了缺失的 LGPL 标头。
    • 修复了两个严重的错误。
  • 2006-04-25
    • 文章创建。
© . All rights reserved.