Skip to content

.NET Core 实战 [No.260~262] 压缩与解压缩

🏷️ 《.NET Core 实战》

System.IO.Compression 命名空间下,.NET Core 框架已经封装了一组常用的类,用于对流进行压缩和解压缩。分别是

  • DeflateStream
  • ZipArchive
  • GZipStream

其中 DeflateStreamGZipStream 均继承自 System.IO.Stream 类。

DeflateStream

DeflateStream 类采用 Deflate 压缩标准算法,属于 huffman 编码的增强版。框架内部默认通过 zlib 实现 DeflateStream 类。

csharp
string inputFilePath = "input-data.json";
string compressedFilePath = "compressed-data.deflate";
string decompressedFilePath = "decompressed-data.json";
// 压缩文件
using (FileStream instream = new FileStream(inputFilePath, FileMode.Open))
using (FileStream outstream = new FileStream(compressedFilePath, FileMode.Create))
using (DeflateStream defstream = new DeflateStream(outstream, CompressionLevel.Optimal))
{
    instream.CopyTo(defstream);
}
// 解压缩文件
using (FileStream outstream = new FileStream(compressedFilePath, FileMode.Open))
using (DeflateStream defstream = new DeflateStream(outstream, CompressionMode.Decompress))
using (FileStream dcstream = new FileStream(decompressedFilePath, FileMode.Create))
{
    defstream.CopyTo(dcstream);
}
// 打印各个文件的大小
FileInfo f1 = new FileInfo(inputFilePath);
FileInfo f2 = new FileInfo(compressedFilePath);
FileInfo f3 = new FileInfo(decompressedFilePath);
Console.WriteLine($"压缩前文件大小:{f1.Length}");
Console.WriteLine($"压缩后文件大小:{f2.Length}");
Console.WriteLine($"解压后文件大小:{f3.Length}");

运行后会输出类似如下的内容。

txt
压缩前文件大小:175988
压缩后文件大小:11311
解压后文件大小:175988

注意: 并非所有文件都能产生较高的压缩比,某些特殊文件在压缩后反而会增大,但增大的幅度较小。

ZipArchive

ZipArchive 类支持对 zip 压缩文档的基本管理,压缩文件中的每个文件(实体)由 ZipArchiveEntry 进行维护。

在下面的示例中,创建了一个压缩文件并写入了 3 个文本文件,最后解压文件到项目根目录。

csharp
string zipFilePath = "demo-data.zip";
// 创建压缩文件,并写入内容
using (FileStream outfs = File.Create(zipFilePath))
using (ZipArchive zip = new ZipArchive(outfs, ZipArchiveMode.Create))
{
    // 第一个文件
    ZipArchiveEntry et1 = zip.CreateEntry("docs/doc1.txt");
    using (Stream stream = et1.Open())
    using (StreamWriter writer = new StreamWriter(stream))
    {
        writer.Write("示例文档 A");
    }
    // 第二个文件
    ZipArchiveEntry et2 = zip.CreateEntry("docs/doc2.txt");
    using (Stream stream = et2.Open())
    using (StreamWriter writer = new StreamWriter(stream))
    {
        writer.Write("示例文档 B");
    }
    // 第三个文件
    ZipArchiveEntry et3 = zip.CreateEntry("docs/doc3.txt");
    using (Stream stream = et3.Open())
    using (StreamWriter writer = new StreamWriter(stream))
    {
        writer.Write("示例文档 C");
    }
}
// 解压文件
using (FileStream instream = File.OpenRead(zipFilePath))
using (ZipArchive zip = new ZipArchive(instream))
{
    foreach (var et in zip.Entries)
    {
        // et.Name 属性仅包含文件名
        // et.FullName 属性包含目录结构
        using (Stream stream = et.Open())
        using (FileStream fsout = File.Create(et.Name))
        {
            stream.CopyTo(fsout);
        }
    }
}

GZipStream

GZIP(全称 GUNzip)用于 Unix 系统的文件压缩,文件后缀为 .gz

.NET Core 框架以 GZipStream 类封装 GZip 算法相关功能,使用方法同 DeflateStream 相同。

csharp
string inFilePath = "input-data.json";
string outFileName = "demo.gz";
string unzipFileName = "unzip-data.json";
// 压缩文件
using (FileStream fsIn = File.OpenRead(inFilePath))
using (FileStream fsOut = File.Create(outFileName))
using (GZipStream gz = new GZipStream(fsOut, CompressionMode.Compress))
{
    fsIn.CopyTo(gz);
}
// 解压缩文件
using (FileStream fsOut = File.OpenRead(outFileName))
using (GZipStream gz = new GZipStream(fsOut, CompressionMode.Decompress))
using (FileStream fsUz = File.Create(unzipFileName))
{
    gz.CopyTo(fsUz);
}
// 打印各个文件的大小
FileInfo f1 = new FileInfo(inFilePath);
FileInfo f2 = new FileInfo(outFileName);
FileInfo f3 = new FileInfo(unzipFileName);
Console.WriteLine($"压缩前文件大小:{f1.Length}");
Console.WriteLine($"压缩后文件大小:{f2.Length}");
Console.WriteLine($"解压后文件大小:{f3.Length}");

运行结果如下:

txt
压缩前文件大小:175988
压缩后文件大小:11329
解压后文件大小:175988

参考:《.NET Core 实战:手把手教你掌握 380 个精彩案例》 -- 周家安 著