前面介绍了六种.NET组件,其中有一种组件是写文件的压缩和解压,现在介绍另一种文件的解压缩组件SharpZipLib。在这个组件介绍系列中,只为简单的介绍组件的背景和简单的应用,读者在阅读时可以结合官网的相关介绍和在本地实际操作。
相关的组件功能非常强大,在笔者的介绍中只是提及到简单的应用,需要了解更多的操作和特性,可以根据官网介绍,或者查看DLL文件的相关类和方法,以此来扩展相关的业务需要。
SharpZipLib是一个完全在C#中为.NET平台编写的Zip,GZip,Tar和BZip2库。
一.SharpZipLib组件概述:
ziplib(SharpZipLib,以前的NZipLib)是一个完全在C#为.NET平台编写的Zip,GZip,Tar和BZip2库。它实现为一个程序集(可安装在GAC中),因此可以轻松地集成到其他项目(任何.NET语言)中。 #ziplib的创建者这样说:“我已经将zip库移植到C#,因为我需要gzip / zip压缩,我不想使用libzip.dll或类似的东西我想要的所有在纯C#“。
SharpZipLib官网提供的下载操作:.NET 1.1,.NET 2.0(3.5,4.0),.NET CF 1.0,.NET CF 2.0的装配:下载237 KB,源代码和示例下载708 KB;源代码和示例下载708 KB;帮助文件下载1208 KB;
SharpZipLib是在GPL下发布,遵守开源协议。
二.SharpZipLib核心类和方法介绍:
以上简单的介绍了SharpZipLib组件的相关背景,现在具体看一下该组件的相关核心类和方法:


1.ZipOutputStream类PutNextEntry():
public void PutNextEntry(ZipEntry entry)
{
bool hasCrc;
if (entry == null)
{
throw new ArgumentNullException("entry");
}
if (this.entries == null)
{
throw new InvalidOperationException("ZipOutputStream was finished");
}
if (this.curEntry != null)
{
this.CloseEntry();
}
if (this.entries.Count == 0x7fffffff)
{
throw new ZipException("Too many entries for Zip file");
}
CompressionMethod compressionMethod = entry.CompressionMethod;
int defaultCompressionLevel = this.defaultCompressionLevel;
entry.Flags &= 0x800;
this.patchEntryHeader = false;
if (entry.Size == 0L)
{
entry.CompressedSize = entry.Size;
entry.Crc = 0L;
compressionMethod = CompressionMethod.Stored;
hasCrc = true;
}
else
{
hasCrc = (entry.Size >= 0L) && entry.HasCrc;
if (compressionMethod == CompressionMethod.Stored)
{
if (!hasCrc)
{
if (!base.CanPatchEntries)
{
compressionMethod = CompressionMethod.Deflated;
defaultCompressionLevel = 0;
}
}
else
{
entry.CompressedSize = entry.Size;
hasCrc = entry.HasCrc;
}
}
}
if (!hasCrc)
{
if (!base.CanPatchEntries)
{
entry.Flags |= 8;
}
else
{
this.patchEntryHeader = true;
}
}
if (base.Password != null)
{
entry.IsCrypted = true;
if (entry.Crc < 0L)
{
entry.Flags |= 8;
}
}
entry.Offset = this.offset;
entry.CompressionMethod = compressionMethod;
this.curMethod = compressionMethod;
this.sizePatchPos = -1L;
if ((this.useZip64_ == UseZip64.On) || ((entry.Size < 0L) && (this.useZip64_ == UseZip64.Dynamic)))
{
entry.ForceZip64();
}
this.WriteLeInt(0x4034b50);
this.WriteLeShort(entry.Version);
this.WriteLeShort(entry.Flags);
this.WriteLeShort((byte) entry.CompressionMethodForHeader);
this.WriteLeInt((int) entry.DosTime);
if (hasCrc)
{
this.WriteLeInt((int) entry.Crc);
if (entry.LocalHeaderRequiresZip64)
{
this.WriteLeInt(-1);
this.WriteLeInt(-1);
}
else
{
this.WriteLeInt(entry.IsCrypted ? (((int) entry.CompressedSize) + 12) : ((int) entry.CompressedSize));
this.WriteLeInt((int) entry.Size);
}
}
else
{
if (this.patchEntryHeader)
{
this.crcPatchPos = base.baseOutputStream_.Position;
}
this.WriteLeInt(0);
if (this.patchEntryHeader)
{
this.sizePatchPos = base.baseOutputStream_.Position;
}
if (entry.LocalHeaderRequiresZip64 || this.patchEntryHeader)
{
this.WriteLeInt(-1);
this.WriteLeInt(-1);
}
else
{
this.WriteLeInt(0);
this.WriteLeInt(0);
}
}
byte[] buffer = ZipConstants.ConvertToArray(entry.Flags, entry.Name);
if (buffer.Length > 0xffff)
{
throw new ZipException("Entry name too long.");
}
ZipExtraData extraData = new ZipExtraData(entry.ExtraData);
if (entry.LocalHeaderRequiresZip64)
{
extraData.StartNewEntry();
if (hasCrc)
{
extraData.AddLeLong(entry.Size);
extraData.AddLeLong(entry.CompressedSize);
}
else
{
extraData.AddLeLong(-1L);
extraData.AddLeLong(-1L);
}
extraData.AddNewEntry(1);
if (!extraData.Find(1))
{
throw new ZipException("Internal error cant find extra data");
}
if (this.patchEntryHeader)
{
this.sizePatchPos = extraData.CurrentReadIndex;
}
}
else
{
extraData.Delete(1);
}
if (entry.AESKeySize > 0)
{
AddExtraDataAES(entry, extraData);
}
byte[] entryData = extraData.GetEntryData();
this.WriteLeShort(buffer.Length);
this.WriteLeShort(entryData.Length);
if (buffer.Length > 0)
{
base.baseOutputStream_.Write(buffer, 0, buffer.Length);
}
if (entry.LocalHeaderRequiresZip64 && this.patchEntryHeader)
{
this.sizePatchPos += base.baseOutputStream_.Position;
}
if (entryData.Length > 0)
{
base.baseOutputStream_.Write(entryData, 0, entryData.Length);
}
this.offset += (30 + buffer.Length) + entryData.Length;
if (entry.AESKeySize > 0)
{
this.offset += entry.AESOverheadSize;
}
this.curEntry = entry;
this.crc.Reset();
if (compressionMethod == CompressionMethod.Deflated)
{
base.deflater_.Reset();
base.deflater_.SetLevel(defaultCompressionLevel);
}
this.size = 0L;
if (entry.IsCrypted)
{
if (entry.AESKeySize > 0)
{
this.WriteAESHeader(entry);
}
else if (entry.Crc < 0L)
{
this.WriteEncryptionHeader(entry.DosTime << 0x10);
}
else
{
this.WriteEncryptionHeader(entry.Crc);
}
}
}
</div>
2.ZipOutputStream类Finish():
public override void Finish()
{
if (this.entries != null)
{
if (this.curEntry != null)
{
this.CloseEntry();
}
long count = this.entries.Count;
long sizeEntries = 0L;
foreach (ZipEntry entry in this.entries)
{
this.WriteLeInt(0x2014b50);
this.WriteLeShort(0x33);
this.WriteLeShort(entry.Version);
this.WriteLeShort(entry.Flags);
this.WriteLeShort((short) entry.CompressionMethodForHeader);
this.WriteLeInt((int) entry.DosTime);
this.WriteLeInt((int) entry.Crc);
if (entry.IsZip64Forced() || (entry.CompressedSize >= 0xffffffffL))
{
this.WriteLeInt(-1);
}
else
{
this.WriteLeInt((int) entry.CompressedSize);
}
if (entry.IsZip64Forced() || (entry.Size >= 0xffffffffL))
{
this.WriteLeInt(-1);
}
else
{
this.WriteLeInt((int) entry.Size);
}
byte[] buffer = ZipConstants.ConvertToArray(entry.Flags, entry.Name);
if (buffer.Length > 0xffff)
{
throw new ZipException("Name too long.");
}
ZipExtraData extraData = new ZipExtraData(entry.ExtraData);
if (entry.CentralHeaderRequiresZip64)
{
extraData.StartNewEntry();
if (entry.IsZip64Forced() || (entry.Size >= 0xffffffffL))
{

