Przeczytaj w języku angielskim

Udostępnij za pośrednictwem


Instrukcje: kompresowanie i wyodrębnianie plików

System.IO.Compression Przestrzeń nazw zawiera następujące klasy do kompresowania i dekompresowania plików i strumieni. Można również użyć tych typów do odczytywania i modyfikowania zawartości skompresowanego pliku:

W poniższych przykładach pokazano niektóre operacje, które można wykonać za pomocą skompresowanych plików. Te przykłady wymagają dodania następujących pakietów NuGet do projektu:

Jeśli używasz programu .NET Framework, dodaj odwołania do tych dwóch bibliotek do projektu:

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

Przykład 1. Tworzenie i wyodrębnianie pliku .zip

W poniższym przykładzie pokazano, jak utworzyć i wyodrębnić skompresowany plik .zip przy użyciu ZipFile klasy . Przykład kompresuje zawartość folderu do nowego pliku .zip , a następnie wyodrębnia plik do nowego folderu.

Aby uruchomić przykład, utwórz folder start w folderze programu i wypełnij go plikami do pliku 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);
    }
}

Przykład 2. Wyodrębnianie określonych rozszerzeń plików

Poniższy przykład wykonuje iterację po zawartości istniejącego pliku .zip i wyodrębnia pliki z rozszerzeniem .txt . Używa ZipArchive klasy w celu uzyskania dostępu do pliku .zip i ZipArchiveEntry klasy w celu sprawdzenia poszczególnych wpisów. Metoda ExtractToFile rozszerzenia obiektu ZipArchiveEntry jest dostępna w System.IO.Compression.ZipFileExtensions klasie .

Aby uruchomić przykład, umieść plik .zip o nazwie result.zip w folderze programu. Po wyświetleniu monitu podaj nazwę folderu do wyodrębnienia.

Ważne

Podczas rozpakowywania plików należy wyszukać złośliwe ścieżki plików, które mogą uciec od katalogu, do którego rozpakujesz. Jest to nazywane atakiem przechodzenia ścieżki. W poniższym przykładzie pokazano, jak sprawdzić pod kątem złośliwych ścieżek plików i zapewnić bezpieczny sposób rozpakuj.

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);
                }
            }
        }
    }
}

Przykład 3. Dodawanie pliku do istniejącego pliku .zip

W poniższym przykładzie użyto ZipArchive klasy , aby uzyskać dostęp do istniejącego pliku .zip i dodaje do niego plik. Nowy plik zostanie skompresowany po dodaniu go do istniejącego pliku .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("========================");
                    }
                }
            }
        }
    }
}

Przykład 4. Kompresowanie i dekompresowanie plików .gz

Klasy i DeflateStream umożliwiają również GZipStream kompresowanie i dekompresowanie danych. Używają tego samego algorytmu kompresji. Można dekompresować GZipStream obiekty zapisywane w pliku .gz przy użyciu wielu popularnych narzędzi. W poniższym przykładzie pokazano, jak kompresować i dekompresować katalog plików przy użyciu GZipStream klasy :

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}");
                }
            }
        }
    }
}

Zobacz też