A volte capita di dover comprimere/decomprimere dei flussi di dati in memoria perché magari li si deve spedire sulla rete tramite socket tcp, web services ecc. ecc. Il compito non è particolarmente difficile e come al solito il framework .Net ci viene incontro fornendoci le “basi” del piatto: MemoryStream per la gestione degli stream in memoria e GZipStream/DeflateStream (per la cui differenza vi rimando all’ottima documentazione su MSDN) per la compressione degli stream.
L’esempio che propongo di seguito mostra appunto l’utilizzo delle classi MemoryStream per il “trasporto” delle informazioni verso la classe “comprimente” che in questo caso ho scelto essere la DeflateStream.
Vediamo per prima cosa la compressione:
public static byte[] Comprimi(byte[] data)
{
MemoryStream ms = new MemoryStream();
DeflateStream ds = new DeflateStream(ms, CompressionMode.Compress);
ds.Write(data, 0, data.Length);
ds.Flush();
ds.Close();
return ms.ToArray();
}
Il contenuto di questo metodo è molto semplice: si passa in input un array di byte, si crea un MemoryStream che conterrà il contenuto dell’array di byte in formato compresso, si crea un DeflateStream che avrà come primo parametro lo stream in cui verrà scritto ciò che si andrà a comprimere, e come secondo parametro la modalità di compressione (compressione/decompressione).
A questo punto tramite il metodo Write possiamo effettivamente scrivere nello stream di memoria l’array di byte compresso.
Qualche riga in più, ma non troppo, per il metodo di decompressione:
public static byte[] Decomprimi(byte[] data)
{
MemoryStream ms = new MemoryStream(data);
DeflateStream ds = new DeflateStream(ms, CompressionMode.Decompress);
Listl = new List();
int theByte = ds.ReadByte();
while (theByte != -1)
{
l.Add((byte)theByte);
theByte = ds.ReadByte();
}
byte[] retVal = l.ToArray();
return retVal;
}
Vediamolo in dettaglio: creeremo un MemoryStream in cui caricheremo dentro l’array di byte compresso. Creeremo un oggetto DeflateStream il cui primo parametro questa volta sarà il MemoryStream con i valory di input e specificheremo che vogliamo applicare a questi una decompressione.
A questo punto leggeremo byte per byte il contenuto del DeflateStream e aggiungeremo il byte letto ad una lista di byte che verray alla fine convertita in un array di byte che finalmente conterrà il contenuto “scompattato” dell’array di partenza.
Se supponiamo d’avere un comune file di testo nella radice del disco “C”, un possibile esempio di quanto visto sopra potrebbe essere:
static void Main(string[] args)
{
byte[] myarray = File.ReadAllBytes(@"C:\TEST.TXT");
byte[] myArrayCompresso = Comprimi(myarray);
byte[] myArrayDecompresso = Decomprimi(myArrayCompresso);
String letto = System.Text.ASCIIEncoding.ASCII.GetString(myArrayDecompresso);
System.Console.WriteLine("Ho letto:\n" + letto + "\n");
Console.WriteLine("Premi per terminare");
Console.ReadLine();
}