#zlib - 修改存档






4.35/5 (9投票s)
2006 年 4 月 27 日
3分钟阅读

79817

819
一种无需完全解压即可修改 Zip 存档的方法。
引言
本文简要介绍了一些类,这些类使您可以修改存档而无需完全解压它。 我解决问题的方式并不是很完美,但它确实有效。 我混合使用了现有的 C# 包装代码 zlib(以及 minizip)和我自己的一些代码。 更好的方法是为 libzip 编写一个包装类。 并且,最好的方法可能是增强 SharpZipLib,以便它可以修改存档。 因此,请随意处理它 ;-)。
另请注意,这些类不支持增强的设置,例如压缩级别或存档注释,因为我不需要它们。 但是您可以轻松添加这些功能。
背景
每个需要在 C# 中进行压缩/解压缩的人很可能会使用来自 IC#Code 的 SharpZipLib。 我也这样做了。 到目前为止。 我一直在使用该库来压缩我的程序生成的数据。 幸运的是,输出都是相同的类型,因此我可以将其保存在同一文件中。 但是现在我有不同类型的数据,这些数据属于程序的不同部分,因此将数据拆分为文件是实现此目的的好方法。 我想在内存中修改这个存档,因为完全解压它相当难看。 我搜索了一段时间,只找到了 Gerry Shaws 的一个旧的 C# 包装类。 我知道 SharpZipLib 对我来说不是一个解决方案,所以我下载了它并尝试使其工作。 它里面有一些错误,导致了一些奇怪的行为,在我用正常的 C# 代码替换了所有不安全的部分后,这些行为消失了(你现在必须这样做,Gerry 的代码有点奇怪;)。 此外,我根据我的需要对代码进行了大量调整。 我用 ZipStream
和 ZipArchive
类替换了他难以处理的 ZipReader
和 ZipWriter
类,这使得读取和写入存档的方式更加容易。 它在某种程度上隐藏了非托管 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 不可爱的部分是,您不能同时打开存档进行读取和写入。 我在我的类中隐藏了这一事实,并且仅公开了 Read
和 Write
函数。 但是,在幕后,每当您从读取函数切换到写入函数或反之亦然时,我的类都会关闭并重新打开存档。 其次,zlib/minizip 不支持任何修改和/或删除文件的可能性。 但是在 minizip 主页上有一个链接到 小型示例,其中包含 Ivan A. Krestinin 编写的有关如何删除文件的 C++ 代码。 我只是将该函数转换为 C#,并将其添加到我的 ZipArchive
类中。 因此,每当您写入现有条目时,旧文件都会首先被删除!
致谢
...去以下人员
历史
- 2006-04-08
- 插入了缺失的 LGPL 标头。
- 修复了两个严重的错误。
- 2006-04-25
- 文章创建。