閱讀英文

共用方式為


操作說明:壓縮與解壓縮檔案

System.IO.Compression 命名空間包含壓縮及解壓縮檔案和資料流的下列類別。 您也可以使用這些類型來讀取和修改壓縮檔案的內容:

下列範例示範您可以搭配壓縮檔案執行的部分作業。 這些範例需要將下列 NuGet 套件新增至您的專案:

如果您是使用 .NET Framework,請將這兩個程式庫的參考新增至您的專案:

  • System.IO.Compression
  • System.IO.Compression.FileSystem

範例 1:建立和解壓縮 ZIP 檔案

下列範例示範如何使用 ZipFile 類別,建立和解壓縮 .zip 檔案。 此範例會將資料夾的內容壓縮至新的 .zip 檔案,然後將該檔案解壓縮至新的資料夾。

若要執行樣本,請在程式資料夾中建立啟動資料夾,並在其中填入要壓縮的檔案。

using System;
using System.IO.Compression;

class Program
{
    static void Main(string[] args)
    {
        string startPath = @".\start";
        string zipPath = @".\result.zip";
        string extractPath = @".\extract";

        ZipFile.CreateFromDirectory(startPath, zipPath);

        ZipFile.ExtractToDirectory(zipPath, extractPath);
    }
}

範例 2:解壓縮特定的副檔名

下列範例會逐一查看現有 .zip 檔案的內容,並將副檔名為 .txt 的檔案解壓縮。 它會使用 ZipArchive 類別來存取 .zip 檔案,以及使用 ZipArchiveEntry 類別來檢查個別項目。 ZipArchiveEntry 物件的擴充方法 ExtractToFile 可在 System.IO.Compression.ZipFileExtensions 類別中使用。

若要執行樣本,請將名為 result.zip.zip 檔案置於您的程式資料夾中。 出現提示時,提供要擷取至的資料夾名稱。

重要

當您在解壓縮檔案時,必須尋找惡意的檔案路徑,以免它從您解壓縮的目的目錄逸出。 這是所謂的路徑周遊攻擊。 以下範例示範如何檢查惡意的檔案路徑,並提供安全的方式來解壓縮。

using System;
using System.IO;
using System.IO.Compression;

class Program
{
    static void Main(string[] args)
    {
        string zipPath = @".\result.zip";

        Console.WriteLine("Provide path where to extract the zip file:");
        string extractPath = Console.ReadLine();

        // Normalizes the path.
        extractPath = Path.GetFullPath(extractPath);

        // Ensures that the last character on the extraction path
        // is the directory separator char.
        // Without this, a malicious zip file could try to traverse outside of the expected
        // extraction path.
        if (!extractPath.EndsWith(Path.DirectorySeparatorChar.ToString(), StringComparison.Ordinal))
            extractPath += Path.DirectorySeparatorChar;

        using (ZipArchive archive = ZipFile.OpenRead(zipPath))
        {
            foreach (ZipArchiveEntry entry in archive.Entries)
            {
                if (entry.FullName.EndsWith(".txt", StringComparison.OrdinalIgnoreCase))
                {
                    // Gets the full path to ensure that relative segments are removed.
                    string destinationPath = Path.GetFullPath(Path.Combine(extractPath, entry.FullName));

                    // Ordinal match is safest, case-sensitive volumes can be mounted within volumes that
                    // are case-insensitive.
                    if (destinationPath.StartsWith(extractPath, StringComparison.Ordinal))
                        entry.ExtractToFile(destinationPath);
                }
            }
        }
    }
}

範例 3:將檔案加入至現有的 .zip 檔案

下列範例使用 ZipArchive 類別存取現有的 .zip 檔案,並將檔案新增至其中。 當您將新檔案加入至現有的 .zip 檔案時,會壓縮該檔案。

using System;
using System.IO;
using System.IO.Compression;

namespace ConsoleApplication
{
    class Program
    {
        static void Main(string[] args)
        {
            using (FileStream zipToOpen = new FileStream(@"c:\users\exampleuser\release.zip", FileMode.Open))
            {
                using (ZipArchive archive = new ZipArchive(zipToOpen, ZipArchiveMode.Update))
                {
                    ZipArchiveEntry readmeEntry = archive.CreateEntry("Readme.txt");
                    using (StreamWriter writer = new StreamWriter(readmeEntry.Open()))
                    {
                            writer.WriteLine("Information about this package.");
                            writer.WriteLine("========================");
                    }
                }
            }
        }
    }
}

範例 4:壓縮和解壓縮 .gz 檔案

您也可以使用 GZipStreamDeflateStream 類別壓縮和解壓縮資料。 它們會使用相同的壓縮演算法。 您可以使用許多常用工具,將寫入至 .gz 檔案的 GZipStream 物件解壓縮。 以下範例示範如何使用 GZipStream 類別壓縮和解壓縮檔案目錄:

using System;
using System.IO;
using System.IO.Compression;

public class Program
{
    private static string directoryPath = @".\temp";
    public static void Main()
    {
        DirectoryInfo directorySelected = new DirectoryInfo(directoryPath);
        Compress(directorySelected);

        foreach (FileInfo fileToDecompress in directorySelected.GetFiles("*.gz"))
        {
            Decompress(fileToDecompress);
        }
    }

    public static void Compress(DirectoryInfo directorySelected)
    {
        foreach (FileInfo fileToCompress in directorySelected.GetFiles())
        {
            using (FileStream originalFileStream = fileToCompress.OpenRead())
            {
                if ((File.GetAttributes(fileToCompress.FullName) &
                   FileAttributes.Hidden) != FileAttributes.Hidden & fileToCompress.Extension != ".gz")
                {
                    using (FileStream compressedFileStream = File.Create(fileToCompress.FullName + ".gz"))
                    {
                        using (GZipStream compressionStream = new GZipStream(compressedFileStream,
                           CompressionMode.Compress))
                        {
                            originalFileStream.CopyTo(compressionStream);
                        }
                    }
                    FileInfo info = new FileInfo(directoryPath + Path.DirectorySeparatorChar + fileToCompress.Name + ".gz");
                    Console.WriteLine($"Compressed {fileToCompress.Name} from {fileToCompress.Length.ToString()} to {info.Length.ToString()} bytes.");
                }
            }
        }
    }

    public static void Decompress(FileInfo fileToDecompress)
    {
        using (FileStream originalFileStream = fileToDecompress.OpenRead())
        {
            string currentFileName = fileToDecompress.FullName;
            string newFileName = currentFileName.Remove(currentFileName.Length - fileToDecompress.Extension.Length);

            using (FileStream decompressedFileStream = File.Create(newFileName))
            {
                using (GZipStream decompressionStream = new GZipStream(originalFileStream, CompressionMode.Decompress))
                {
                    decompressionStream.CopyTo(decompressedFileStream);
                    Console.WriteLine($"Decompressed: {fileToDecompress.Name}");
                }
            }
        }
    }
}

另請參閱


其他資源