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.
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();