DeflateStream e GZipStream sono due classi presenti nel nuovo namespace System.IO.Compression il cui scopo è quello di comprimere/decomprimere streams.
L'interfaccia delle due classi è simile e condividono lo stesso algoritmo di compressione, GZip aggiunge un CRC per verificare l'integrita' dei dati e, volendo, puo' essere esteso affiche' usi altri formati di conversione. Qui descriverò solo DeflateStream.
Ecco un esempio di come comprimere un file:
private
static void Compress(string sourceFile, string outputFile)
{
using (FileStream fs = new FileStream(sourceFile, FileMode.Open))
{
using (MemoryStream ms = new MemoryStream())
{
using (DeflateStream ds = new DeflateStream(ms, CompressionMode.Compress))
{
byte[] data = new byte[fs.Length - 1];
fs.Read(data, 0, data.Length);
ds.Write(data, 0, data.Length);
using (FileStream ws = new FileStream(outputFile, FileMode.Create))
{
ws.Write(ms.ToArray(), 0, (int)ms.Length);
ws.Flush();
}
}
}
}
}
Nulla di complicato, si tratta solo di passare a DeflateStream il valore CompressionMode.Compress.
Il processo contrario è invece leggermente diverso in quanto le proprietà Lenght,Position e Seek di DeflateStream generano una NotSupportedException e questo obbliga a leggere lo stream decompresso a "blocchi" fino a quando il valore dei bytes letti è uguale a zero (vedi GetStream())
private
static void DeCompress(string sourceFile, string outputFile)
{
using (FileStream fs = new FileStream(sourceFile, FileMode.Open))
{
using (MemoryStream ms = new MemoryStream((int)fs.Length))
{
using (DeflateStream ds = new DeflateStream(ms, CompressionMode.Decompress,true))
{
byte[] dataIn = new byte[fs.Length - 1];
fs.Read(dataIn, 0, dataIn.Length);
ms.Write(dataIn, 0, dataIn.Length);
ms.Position = 0;
byte[] data = Program.GetStream(ds);
using (FileStream ws = new FileStream(outputFile, FileMode.Create))
{
ws.Write(data, 0, data.Length);
ws.Flush();
}
}
}
}
}
private static byte[] GetStream(Stream stream)
{
byte[] buffer = new byte[10000];
using (MemoryStream ms = new MemoryStream())
{
while (true)
{
int bytesRead = stream.Read(buffer, 0, 10000);
if (bytesRead <= 0) return ms.ToArray();
ms.Write(buffer, 0, bytesRead);
}
}
}
Comprimendo Streams le classi si prestano per gli usi più disparati, accoppiate alle classi di serializzazione possono, ad esempio, diminuire lo spazio occupato da un oggetto serializzato, qui trovate una classe basata su DeflateStream che comprime/decomprime la classe DataSet.