知识库

使用 C# 对文件进行 Zip 或解压 - 文件压缩与解压

什么是 ZIP(文件格式)

ZIP 是一种支持无损数据压缩的归档文件格式。一个 ZIP 文件可以包含一个或多个已压缩的文件或目录。ZIP 文件通常使用扩展名 .zip.ZIP,其 MIME 类型为 application/zip。许多程序都以不同的名称将 ZIP 作为基础文件格式使用。在文件系统的图形用户界面中,ZIP 文件的图标常常表现为带有拉链图案的文档或其他对象。

多种方式对文件进行压缩(zip) ,具体取决于您使用的操作系统。几乎每天我们都需要对文件进行压缩或解压,并将其上传到存储服务器或文件共享平台。幸运的是,您可以使用Aspose.ZIP API 来自动化此过程。该 API 让您在不关心底层文件结构的情况下实现文件的压缩与解压。本文展示了单文件和多文件压缩的完整示例。

Aspose.ZIP 包可以通过以下 NuGet 命令添加到您的 .NET 项目中:

PM> Install-Package Aspose.Zip

使用 C# 压缩单个文件

  1. 首先需要为输出的 ZIP 归档创建一个FileStream 类 对象。
  2. 将单个文件加载到FileStream 对象中。
  3. 创建一个Archive 类 的实例。
  4. 使用 Archive.CreateEntry("FileName", FileStream) 方法将文件添加到归档中。
  5. 使用 Archive.Save(FileStream) 方法生成 ZIP 归档。
using (FileStream zipFile = File.Open(dataDir + "CompressSingleFile_out.zip", FileMode.Create))
{
    // 要添加到归档的文件
    using (FileStream source1 = File.Open(dataDir + "alice29.txt", FileMode.Open, FileAccess.Read))
    {
        using (var archive = new Archive(new ArchiveEntrySettings()))
        {
            archive.CreateEntry("alice29.txt", source1);
            archive.Save(zipFile);
        }
    }
}

使用 C# 压缩多个文件

压缩多个文件与压缩单个文件的区别在于,需要将更多的文件加载到 FileStream 中,并使用 Archive.CreateEntry("FileName", FileStream) 方法逐一添加到 ZIP 归档。下面的代码片段演示了如何使用 FileStream 将多个文件添加到 ZIP 中。

// 为输出的 ZIP 归档创建 FileStream
using (FileStream zipFile = File.Open("compressed_files.zip", FileMode.Create))
{
    // 第一个要添加的文件
    using (FileStream source1 = File.Open("alice29.txt", FileMode.Open, FileAccess.Read))
    {
        // 第二个要添加的文件
        using (FileStream source2 = File.Open("asyoulike.txt", FileMode.Open, FileAccess.Read))
        {
            using (var archive = new Archive())
            {
                // 将文件添加到归档
                archive.CreateEntry("alice29.txt", source1);
                archive.CreateEntry("asyoulik3.txt", source2);
                // 为归档添加注释并保存
                archive.Save(zipFile, new ArchiveSaveOptions() { Encoding = Encoding.ASCII, ArchiveComment = "two files are compressed in this archive" });
            }
        }
    }
}

使用 FileInfo 类压缩文件

文件也可以通过 FileInfo 类加载,然后以同样的方式添加到 ZIP 归档中。FileInfo 类提供了创建、复制、删除、移动和打开文件的属性与实例方法,并帮助生成 FileStream 对象。

using (FileStream zipFile = File.Open("compressed_files.zip", FileMode.Create))
{
    // 要添加到归档的文件
    FileInfo fi1 = new FileInfo("alice29.txt");
    FileInfo fi2 = new FileInfo("fields.c");
    using (var archive = new Archive())
    {
        // 将文件添加到归档
        archive.CreateEntry("alice29.txt", fi1);
        archive.CreateEntry("fields.c", fi2);
        // 创建 ZIP 归档
        archive.Save(zipFile, new ArchiveSaveOptions() { Encoding = Encoding.ASCII });
    }
}

将文件存储到归档而不进行压缩

// 创建不压缩文件的 zip 归档
using (FileStream zipFile = File.Open(dataDir + "StoreMultipleFilesWithoutCompression_out.zip", FileMode.Create))
{
    FileInfo fi1 = new FileInfo(dataDir + "alice29.txt");
    FileInfo fi2 = new FileInfo(dataDir + "lcet10.txt");

    using (Archive archive = new Archive(new ArchiveEntrySettings(new StoreCompressionSettings())))
    {
        archive.CreateEntry("alice29.txt", fi1);
        archive.CreateEntry("lcet10.txt", fi2);
        archive.Save(zipFile, new ArchiveSaveOptions() { Encoding = Encoding.ASCII });
    }
}

使用密码压缩 ZIP 文件(C#)

using (var archive = new Archive(new ArchiveEntrySettings(encryptionSettings: new TraditionalEncryptionSettings("pass"))))
{
    archive.CreateEntry("entry_name1.dat", "input_file1.dat");
    archive.CreateEntry("entry_name2.dat", "input_file2.dat");
    archive.Save("result_archive.zip");
}

encryptionSettings 参数用于创建受密码保护的 ZIP 归档。

使用密码解压 ZIP 文件(C#)

using (var archive = new Archive("input_archive.zip", new ArchiveLoadOptions{DecryptionPassword = "pass"}))
{
    archive.ExtractToDirectory("\\outputDirectory");
}

ArchiveLoadOptions 中的 DecryptionPassword 属性用于打开受密码保护的 ZIP 归档。

要查看完整示例和数据文件,请访问 https://github.com/aspose-zip/Aspose.ZIP-for-.NET

在 ZIP 归档中使用 LZMA 压缩

Lempel–Ziv–Markov 链算法(LZMA)是一种用于实现无损数据压缩的算法。LZMA 使用字典压缩技术,压缩后的数据流是位流。将 LZMA 压缩用于 ZIP 归档时,ZIP 容器可以包含 LZMA 压缩的条目。以下代码示例演示了使用Aspose.ZIP API 实现 LZMA 压缩。

using (FileStream zipFile = File.Open(dataDir + "LZMACompression_out.zip", FileMode.Create))
{
    using (Archive archive = new Archive(new ArchiveEntrySettings(new LzmaCompressionSettings())))
    {
        archive.CreateEntry("sample.txt", dataDir + "sample.txt");
        archive.Save(zipFile);
    }
}

在 ZIP 归档中使用 BZip2 压缩

bzip2 是一种免费且开源的文件压缩程序,采用 Burrows–Wheeler 算法。它仅压缩单个文件,并非文件归档工具。bzip2 由 Julian Seward 开发,后由 Mark Wielaard 和 Micah Snyder 维护。以下代码片段展示了使用Aspose.ZIP API 实现 BZip2 压缩。

using (FileStream zipFile = File.Open(dataDir + "Bzip2Compression_out.zip", FileMode.Create))
{
    using (Archive archive = new Archive(new ArchiveEntrySettings(new Bzip2CompressionSettings())))
    {
        archive.CreateEntry("sample.txt", dataDir + "sample.txt");
        archive.Save(zipFile);
    }
}

在 ZIP 归档中使用 PPMd 压缩

基于部分匹配的预测(PPM)是一种自适应统计数据压缩技术,基于上下文建模与预测。PPM 模型利用未压缩符号流中的前置符号集合来预测流中的下一个符号。PPM 算法也可用于聚类分析中的数据分组预测。以下代码片段展示了使用Aspose.ZIP API 实现 PPMd 压缩。

using (FileStream zipFile = File.Open(dataDir + "PPMdCompression_out.zip", FileMode.Create))
{
    using (Archive archive = new Archive(new ArchiveEntrySettings(new PPMdCompressionSettings())))
    {
        archive.CreateEntry("sample.txt", dataDir + "sample.txt");
        archive.Save(zipFile);
    }
}

解压单文件归档

using (FileStream fs = File.OpenRead(dataDir + "CompressSingleFile_out.zip"))
{
    using (Archive archive = new Archive(fs))
    {
        int percentReady = 0;
        archive.Entries[0].ExtractionProgressed += (s, e) =>
        {
            int percent = (int)((100 * e.ProceededBytes) / ((ArchiveEntry)s).UncompressedSize);
            if (percent > percentReady)
            {
                Console.WriteLine(string.Format("{0}% decompressed", percent));
                percentReady = percent;
            }
        };
        archive.Entries[0].Extract(dataDir + "alice_extracted_out.txt");
    }
}

解压多文件归档

using (FileStream zipFile = File.Open(dataDir + "CompressMultipleFiles_out.zip", FileMode.Open))
{
    StringBuilder sb = new StringBuilder("Entries are: ");
    int percentReady = 0;
    using (Archive archive = new Archive(zipFile,
        new ArchiveLoadOptions()
        {
            EntryListed = (s, e) => { sb.AppendFormat("{0}, ", e.Entry.Name); },
            EntryExtractionProgressed = (s, e) =>
            {
                int percent = (int)((100 * e.ProceededBytes) / ((ArchiveEntry)s).UncompressedSize);
                if (percent > percentReady)
                {
                    Console.WriteLine(string.Format("{0}% compressed", percent)); percentReady = percent;
                }
            }
        }))
    {
        Console.WriteLine(sb.ToString(0, sb.Length - 2));
        using (var extracted = File.Create(dataDir + "alice_extracted_out.txt"))
        {
            using (var decompressed = archive.Entries[0].Open())
            {
                byte[] buffer = new byte[8192];
                int bytesRead;
                while (0 < (bytesRead = decompressed.Read(buffer, 0, buffer.Length)))
                {
                    extracted.Write(buffer, 0, bytesRead);
                }
                // 从解压流读取并写入目标文件
            }
        }
        percentReady = 0;
        archive.Entries[1].Extract(dataDir + "asyoulik_extracted_out.txt");
    }
}

解压未压缩的存储归档

using (FileStream zipFile = File.Open(dataDir + "StoreMultipleFilesWithoutCompression_out.zip", FileMode.Open))
{
    using (Archive archive = new Archive(zipFile))
    {
        using (var extracted = File.Create(dataDir + "alice_extracted_store_out.txt"))
        {
            using (var decompressed = archive.Entries[0].Open())
            {
                byte[] buffer = new byte[8192];
                int bytesRead;
                while (0 < (bytesRead = decompressed.Read(buffer, 0, buffer.Length)))
                {
                    extracted.Write(buffer, 0, bytesRead);
                }
                // 从解压流读取并写入目标文件
            }
        }

        using (var extracted = File.Create(dataDir + "asyoulik_extracted_store_out.txt"))
        {
            using (var decompressed = archive.Entries[1].Open())
            {
                byte[] buffer = new byte[8192];
                int bytesRead;
                while (0 < (bytesRead = decompressed.Read(buffer, 0, buffer.Length)))
                {
                    extracted.Write(buffer, 0, bytesRead);
                }
                // 从解压流读取并写入目标文件
            }
        }
    }
}

要获取完整示例和数据文件,请访问 https://github.com/aspose-zip/Aspose.ZIP-for-.NET