如何使用 System.IO.Compression 读写 ZIP 文件?

20

我知道有一些处理ZIP文件的库可用。另外,你也可以使用Windows内置的ZIP文件功能

但是,我想知道是否有人已经探索了如何使用.NET中System.IO.Compression命名空间内置的工具读/写ZIP文件?或者说,只使用此命名空间是否不可能?

更新:我看到有人评论说System.IO.Packaging命名空间也可能有用。有人知道具体如何做吗?

9个回答

17

5
实际上,System.IO.Packaging 命名空间包含用于处理开放式封装风格的包的类。您可以使用它来创建 ZIP 文件(如果您不关心将包括在ZIP文件中的某些额外文件),但它不能用于打开 任何 zip 文件。有关更多信息,请参见 ZipPackage 类文档底部的内容(虽然此社区未出现在 .NET 4.0 文档中,但仍然有效)。 - larsmoa

7

7
您需要使用第三方库,例如http://www.codeplex.com/DotNetZip,而不是尝试使用GZipStream或DeflateStream来读取zip文件。
.NET中的***Stream类可以让您读取或写入压缩的字节流。这些类不会读取或写入zip文件。zip文件是被“信封”或头部包围的压缩数据。将其视为元数据——它包含文件名、时间戳、CRC和一堆其他信息。**Stream类仅生成压缩数据流,并不知道如何生成或消费元数据,这在由PKWare维护的PKZip格式规范中有所描述。
像DotNetZip这样的第三方库处理ZIP归档中的元数据。它们可能使用System.IO.Compression.DeflateStream()类来生成压缩的字节流,也可能不使用。例如,在以前的版本中,DotNetZip使用内置的DeflateStream。从v1.7开始,DotNetZip包含了自己的DeflateStream,比.NET Framework中附带的更高效。作为附加好处,嵌入式DeflateStream使DotNetZip可以在缺少System.IO.Compression.DeflateStream的.NET Compact Framework 2.0上使用。(它在Compact Framework 3.5中添加)
如果您有更多问题,DotNetZip网站上有一个良好的论坛。以下是示例C#代码:
    try
    {
        using (ZipFile zip = new ZipFile())
        {
            zip.AddDirectory(DirectoryToZip); // recurses subdirs
            zip.Save(Filename);
        }
    }
    catch (System.Exception ex1)
    {
        System.Console.Error.WriteLine("exception: " + ex1);
    }

6
自从.NET 4.5以来,微软就在System.IO.Compression命名空间中提供了ZipArchive类。与该命名空间中的其他类(例如GZipStream和Deflate流)不同的是,ZipArchive需要引用System.IO.Compression.dll程序集。
它非常简单易用,上面的MSDN链接提供了一些很好的示例。
此外,微软还创建了Microsoft Compression NuGet包,为Windows Phone 8和其他可移植类库添加了对ZipArchive和相关类的支持。

4

虽然这是一个较旧的帖子,但我想指出.NET 4.5已经大量改进了system.io.compression系统。现在它可以很好地处理.zip文件,甚至可以将压缩文件内的单个文件公开为流来读写,而不需要解压和压缩文件。



0

虽然这是一个旧的线程,但我想分享我发现的最简单的解决方案,只使用一行代码(读/写)中的System.IO.Compression:

System.IO.Compression.ZipFile.ExtractToDirectory(sourceArchiveFileName, destinationDirectoryName);
System.IO.Compression.ZipFile.CreateFromDirectory(directoryToArchivePath, archiveDestinationPath);

0

是的,我以前用过它。 我曾经子类化DataSet一次,以支持将自己持久化到文件中(通过ReadXML / WriteXML方法)。 作为额外的奖励,我决定允许它在需要时选择性地进行压缩(正如您所有人应该已经知道的那样,这对于像XML这样的文本数据非常有效)。

我使用了GZipStream类(当时我的理解是相关的DeflateStream仅仅是没有头信息的GZip,或者类似这样——我相信有人可以纠正我)。它通过在另一个流的基础上进行附加来简单地工作,因此您可以使用GZipStream代替它。在我的情况下,它是在FileStream上进行附加。

给定一个MemoryStream以填充myDataSet.WriteXML()的输出,我做了类似以下的事情:

if (CompressData)
{
    // Write to memory
    mStream = new MemoryStream();
    Save(mStream);
    mStream.Seek(0, SeekOrigin.Begin);

    // Filter that through a GZipStream and then to file
    fStream = new FileStream(Path.Combine(CacheFilePath, FileName + ".gz"),
                             FileMode.OpenOrCreate);
    zipStream = new GZipStream(fStream, CompressionMode.Compress, true);

    Pump(mStream, zipStream);
}
else
{
    // Write straight to file
    fStream = new FileStream(Path.Combine(CacheFilePath, FileName),
                             FileMode.OpenOrCreate);
    Save(fStream);
}

Save()Pump() 是如下简单方法:

private void Pump(Stream input, Stream output)
{
    int n;
    byte[] bytes = new byte[4096]; // 4KiB at a time

    while ((n = input.Read(bytes, 0, bytes.Length)) != 0)
    {
        output.Write(bytes, 0, n);
    }
}

public void Save(Stream stream)
{
    AcceptChanges();

    WriteXml(stream, XmlWriteMode.WriteSchema);
}

您的解决方案不会读取或写入ZIP文件格式,而只是针对原始deflate压缩或GZip简单头尾扩展进行压缩。 - Martin Plante
+1你的答案可能不会创建ZIP文件,但它确实展示了如何使用System.IO.Compression,在SSIS中压缩文件非常有用,因为你受限于.NET 2.0并且难以使用外部库。 - bstoney

0
    public static void zIpDatabseFile(string srcPath, string destPath)
    {//This is for  Zip a File
        using (var source = new FileStream(srcPath, FileMode.Open, FileAccess.Read, FileShare.Read))
        using (var dest = new FileStream(destPath, FileMode.OpenOrCreate, FileAccess.Write))
        using (var zip = new GZipStream(dest, CompressionMode.Compress))
        {
            source.CopyTo(zip);
        }
    }
    public static void uNzIpDatabaseFile(string SrcPath, string DestPath)
    {// This is for unzip a files.
        using (var source = new FileStream(SrcPath, FileMode.Open, FileAccess.Read, FileShare.Read))
        using (var dest = new FileStream(DestPath, FileMode.OpenOrCreate, FileAccess.Write))
        using (var zip = new GZipStream(source, CompressionMode.Decompress))
        {
            zip.CopyTo(dest);
        }
    }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接