Baza wiedzy

Kompresowanie i dekompresowanie plików ZIP w C# – kompresja i dekompresja plików

Co to jest format ZIP

ZIP jest formatem archiwum, który obsługuje bezstratną kompresję danych. Plik ZIP może zawierać jeden lub więcej plików lub katalogów, które zostały skompresowane. Pliki ZIP zazwyczaj używają rozszerzeń .zip lub .ZIP oraz typu MIME application/zip. ZIP jest wykorzystywany jako podstawowy format plików przez wiele programów, często pod inną nazwą. W interfejsie użytkownika ikony graficzne reprezentujące pliki ZIP często wyglądają jak dokument lub inny obiekt z wyraźnym symbolem zamka błyskawicznego.
Istnieją różne sposoby kompresowania (zipowania) plików ; zależy to od używanego systemu operacyjnego. Praktycznie codziennie musimy spakować lub rozpakować pliki i przesłać je na serwer lub platformę udostępniania plików. Na szczęście możemy zautomatyzować ten proces przy użyciu Aspose.ZIP API . Umożliwia on kompresję i dekompresję plików bez martwienia się o ich wewnętrzną strukturę. Ten artykuł pokazuje, jak pracować z kompresją pojedynczych oraz wielu plików.
Pakiet Aspose.ZIP można dodać do projektu .NET za pomocą następującego polecenia NuGet:

PM> Install-Package Aspose.Zip

Jak skompresować pojedynczy plik w C#

  1. Najpierw musimy utworzyć obiekt klasy FileStream dla wyjściowego archiwum ZIP.
  2. Załadować pojedynczy plik do obiektu FileStream .
  3. Utworzyć obiekt klasy Archive .
  4. Dodać plik do archiwum przy użyciu metody Archive.CreateEntry („FileName”, FileStream).
  5. Utworzyć archiwum ZIP przy użyciu metody Archive.Save (FileStream).
using (FileStream zipFile = File.Open(dataDir + "CompressSingleFile_out.zip", FileMode.Create))
{
    // Plik do dodania do archiwum
    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);
        }
    }
}

Kompresowanie wielu plików w C#

Różnica między kompresowaniem jednego pliku a wieloma polega na tym, że musimy wczytać więcej plików do obiektów FileStream i dodać je wszystkie do archiwum ZIP przy użyciu metody Archive.CreateEntry("FileName", FileStream).
Poniższy fragment kodu pokazuje, jak dodać wiele plików do ZIP przy użyciu FileStream.

// Utwórz FileStream dla wyjściowego archiwum ZIP
using (FileStream zipFile = File.Open("compressed_files.zip", FileMode.Create))
{
    // Plik do dodania do archiwum
    using (FileStream source1 = File.Open("alice29.txt", FileMode.Open, FileAccess.Read))
    {
        // Drugi plik do dodania do archiwum
        using (FileStream source2 = File.Open("asyoulike.txt", FileMode.Open, FileAccess.Read))
        {
            using (var archive = new Archive())
            {
                // Dodaj pliki do archiwum
                archive.CreateEntry("alice29.txt", source1);
                archive.CreateEntry("asyoulik3.txt", source2);
                // Spakuj pliki
                archive.Save(zipFile, new ArchiveSaveOptions() { Encoding = Encoding.ASCII, ArchiveComment = "two files are compressed in this archive" });
            }
        }
    }
}

Kompresowanie plików przy użyciu klasy FileInfo

Pliki można również wczytać przy pomocy klasy FileInfo i później dodać do archiwum ZIP w taki sam sposób, jak wcześniej.
Klasa FileInfo udostępnia właściwości i metody instancyjne służące do tworzenia, kopiowania, usuwania, przenoszenia i otwierania plików oraz ułatwia tworzenie obiektów FileStream.

using (FileStream zipFile = File.Open("compressed_files.zip", FileMode.Create))
{
    // Pliki do dodania do archiwum
    FileInfo fi1 = new FileInfo("alice29.txt");
    FileInfo fi2 = new FileInfo("fields.c");
    using (var archive = new Archive())
    {
        // Dodaj pliki do archiwum
        archive.CreateEntry("alice29.txt", fi1);
        archive.CreateEntry("fields.c", fi2);
        // Utwórz archiwum ZIP
        archive.Save(zipFile, new ArchiveSaveOptions() { Encoding = Encoding.ASCII });
    }
}

Przechowywanie plików w archiwach bez kompresji

// Tworzy archiwum zip bez kompresowania plików
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 });
    }
}

Jak spakować pliki ZIP z hasłem w 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");
}

Parametr encryptionSettings służy do utworzenia archiwum ZIP zabezpieczonego hasłem.

Jak rozpakować pliki ZIP z hasłem w C#

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

ArchiveLoadOptions z właściwością DecryptionPassword służy do otwarcia archiwum ZIP zabezpieczonego hasłem.
Aby zobaczyć pełne przykłady i pliki danych, przejdź do https://github.com/aspose-zip/Aspose.ZIP-for-.NET .

Użycie kompresji LZMA w archiwum ZIP

Algorytm Lempel–Ziv–Markov chain (LZMA) jest algorytmem służącym do bezstratnej kompresji danych. LZMA wykorzystuje kompresję słownikową, a skompresowany strumień jest ciągiem bitów. Kompresja LZMA w archiwum ZIP pozwala kontenerom ZIP zawierać wpisy skompresowane metodą LZMA. Poniższy przykład kodu pokazuje implementację kompresji LZMA przy użyciu Aspose.ZIP API .

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

Użycie kompresji BZip2 w archiwum ZIP

bzip2 to darmowy i otwarto‑źródłowy program do kompresji plików, który wykorzystuje algorytm Burrowsa–Whelera. Kompresuje jedynie pojedyncze pliki i nie jest archiwizatorem. Został opracowany przez Juliana Sewarda oraz jest utrzymywany przez Marka Wielaarda i Micaha Snydera. Poniższy fragment kodu pokazuje implementację kompresji BZip2 przy użyciu Aspose.ZIP API .

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

Użycie kompresji PPMd w archiwum ZIP

Prediction by partial matching (PPM) to adaptacyjna technika statystycznej kompresji danych oparta na modelowaniu kontekstu i prognozowaniu. Modele PPM wykorzystują zestaw poprzednich symboli w niekompresowanym strumieniu, aby przewidzieć kolejny symbol. Algorytmy PPM mogą być także używane do grupowania danych w przewidywane klastry w analizie skupień. Poniższy fragment kodu pokazuje implementację kompresji PPMd przy użyciu Aspose.ZIP API .

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

Dekompresja archiwum z jednym plikiem

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

Dekompresja archiwum z wieloma plikami

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);
                }
                // Read from decompressed stream to extracting file.
            }
        }
        percentReady = 0;
        archive.Entries[1].Extract(dataDir + "asyoulik_extracted_out.txt");
    }
}

Wyodrębnianie archiwum przechowywanego bez kompresji

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);
                }
                // Read from decompressed stream to extracting file.
            }
        }

        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);
                }
                // Read from decompressed stream to extracting file.
            }
        }
    }
}

Aby uzyskać pełne przykłady i pliki danych, przejdź do https://github.com/aspose-zip/Aspose.ZIP-for-.NET .