Kompresja strumieni

TeWuX

Od wersji .NET 2.0 zostały udostępnione nam strumienie kompresujące. Znajdują się one w przestrzeni nazw:

using System.IO.Compression;

Są to:
*DeflateStream
*GZipStream
Przy czym musimy pamiętać, ze do kompresji i dekompresji musimy używać tego samego strumienia.

Mimo że GZip korysta z algorytmu Deflate, to GZipStream dodaje do plików róznego rodzaju nagłówki, dzięki czemu będziemy mogli uruchomić skompresowane pliki np. w WinZIPie.

Natomiast DeflateStream stosuję czystą kompresję, przez co nie uruchomimy tak skompresowanego pliku w większości archiwizerów.
Więc jeśli kompresować i dekompresować będziemy wyłącznie w naszym programie możemy spokojnie użyć DeflateStream.

DeflateStream compressionStream = new DeflateStream(outputStream, CompressionMode.Compress);

CompressionMode służy do ustawienia, czy mamy kompresować czy dekompresować dane:
*CompressionMode.Compress - kompresja
*CompressionMode.Decompress - dekompresja
Aby użyć kompresji, należy strumień kompresujący przekierować na inny strumień np. FileStream.

Przykład 1:

public void SaveToFile(string FileName)
 {
     FileStream fsOutput = new FileStream(FileName, FileMode.Create);
     GZipStream gZip = new GZipStream(fsOutput, CompressionMode.Compress);
     byte[] buf = { 10, 12, 40, 32, 17 }; //przykładowa tablica byte'ów
     gZip.Write(buf, 0, buf.Length);
     gZip.Close();
     fsOutput.Close();
 }

Metoda z przykładu 1. kompresuje tablicę byte'ów buf i zapisuje do pliku skompresowaną.

A co jeśli chcemy skompresować coś innego, np. tekst?
Musimy stworzyć następny strumień np. StreamWriter, który będzie przekierowywany na strumień kompresji, a ten z kolei do pliku ;-)

Przykład 2:

public void SaveToFile(string FileName)
 {
      FileStream fsOutput = new FileStream(FileName, FileMode.Create);
      GZipStream gZip = new GZipStream(fsOutput, CompressionMode.Compress);
      StreamWriter writer = new StreamWriter(gZip);
      writer.WriteLine("Ala ma kota.";
      writer.WriteLine("Kot ma buty :-)");
      writer.Close();
      gZip.Close();
      fsOutput.Close();
 }

Tym samym sposobem możemy skompresować cały plik. Wystarczy stworzyć kolejny strumień pliku:

FileStream fsInput = new FileStream(FileName, FileMode.Open);

który będzie zawierał plik źródłowy.
Następnie kopiujemy dane ze strumienia fsInput do strumienia kompresji gZip.

Dekompresja strumieni jest analogiczna do kompresji:

Przykład 3:

string tekst;

public void LoadFromFile(string FileName)
 {
     FileStream fsInput = new FileStream(FileName, FileMode.Open);
     GZipStream gZip = new GZipStream(fsInput, CompressionMode.Decompress);
     StreamReader reader = new StreamReader(gZip);
     tekst = reader.ReadLine();
     reader.Close();
     gZip.Close();
     fsInput.Close();
 }

Przykłady, które przedstawiłem nie są zabezpieczone przed ewentualnymi błędami np. gdy plik nie istnieje. Przykłady miały pokazać jedynie główny sens korzystania ze strumieni kompresujących.

1 komentarz

ogólnie nie jestem pewien, czy musze zamykać wszystkie strumienie pokolei.

Prawdopodomnie wystarczy zamknąć podstawowy strumień. Z takim czymś się spotkałem.

Czyli zamiast:
reader.Close();
gZip.Close();
fsInput.Close();

wystarczy:
fsInput.Close();