2009-06-08 14 views
5

Sto comprimendo i risultati da QUERYS del database prima di aggiungerli alla cache.Come comprimere un'istanza dell'oggetto .net utilizzando gzip

Desidero essere in grado di comprimere qualsiasi tipo di riferimento.

ho una versione funzionante di questo per comprimere le stringhe .. l'idea sulla base di post del blog di Scott Hanselman s' http://shrinkster.com/173t

qualche idea per la compressione di un oggetto .NET?

So che sarà una cache di sola lettura poiché gli oggetti nella cache sarà solo array di byte ..

risposta

20

Questo non funziona per qualsiasi tipo di riferimento. Funzionerà per i tipi Serializable. Collegare un BinaryFormatter a un flusso di compressione che viene convogliato in un file:

var formatter = new BinaryFormatter(); 
using (var outputFile = new FileStream("OutputFile", FileMode.CreateNew)) 
using (var compressionStream = new GZipStream(
         outputFile, CompressionMode.Compress)) { 
    formatter.Serialize(compressionStream, objToSerialize); 
    compressionStream.Flush(); 
} 

È possibile utilizzare un MemoryStream per contenere i contenuti in memoria, piuttosto che scrivere su un file. Dubito che questa sia davvero una soluzione efficace per un cache, comunque.

+1

grazie, questo è stato davvero utile, come sarebbe la decompressione ... mai usato BinaryFormatter prima. –

+0

Grazie per averlo facilmente modificato + pastable nel mio codice. Formatto le cose abbastanza spesso che ora è solo un frammento che posso facilmente trovare su Google. +1 –

3

Che tipo di oggetti stai inserendo nella cache? Sono oggetti digitati? O cose come DataTable? Per DataTable, quindi memorizzare come xml compresso tramite GZipStream. Per gli oggetti digitati (entità), probabilmente dovrai serializzarli.

Si potrebbe utilizzare BinaryFormatter e GZipStream, o si può solo usare qualcosa come protobuf-net serializzazione (gratuito), che è già molto compatto (aggiungendo GZipStream rende in genere i dati grande - che è tipica della fitta binario). In particolare, il vantaggio di cose come protobuf-net è che si ottiene la dimensione ridotta senza dover pagare il costo della CPU per decomprimerlo durante la deserializzazione. In some testsprima del, aggiungendo GZipStream, era 4 volte più veloce di BinaryFormatter. Aggiungi il tempo supplementare a BinaryFormatter per GZip e dovrebbe vincere con un margine di considerevole.

2

Ho appena aggiunto il supporto GZipStream per la mia app oggi, quindi posso condividere del codice qui;

serializzazione:

using (Stream s = File.Create(PathName)) 
{ 
    RijndaelManaged rm = new RijndaelManaged(); 
    rm.Key = CryptoKey; 
    rm.IV = CryptoIV; 
    using (CryptoStream cs = new CryptoStream(s, rm.CreateEncryptor(), CryptoStreamMode.Write)) 
    { 
     using (GZipStream gs = new GZipStream(cs, CompressionMode.Compress)) 
     { 
      BinaryFormatter bf = new BinaryFormatter(); 
      bf.Serialize(gs, _instance); 
     } 
    } 
} 

deserializzazione:

using (Stream s = File.OpenRead(PathName)) 
{ 
    RijndaelManaged rm = new RijndaelManaged(); 
    rm.Key = CryptoKey; 
    rm.IV = CryptoIV; 
    using (CryptoStream cs = new CryptoStream(s, rm.CreateDecryptor(), CryptoStreamMode.Read)) 
    { 
     using (GZipStream gs = new GZipStream(cs, CompressionMode.Decompress)) 
     { 
      BinaryFormatter bf = new BinaryFormatter(); 
      _instance = (Storage)bf.Deserialize(gs); 
     } 
    } 
} 

NOTA: se si utilizza CryptoStream, è un po importante catena (dis) zippare e (de) crypting proprio in questo modo, perché ti conviene perdere la tua entropia PRIMA la crittografia crea rumore dai tuoi dati.

Problemi correlati