2009-06-08 5 views
5

Je veux compresser les résultats de QUERYS de la base de données avant de les ajouter au cache.Comment compresser une instance d'objet .net en utilisant gzip

Je veux pouvoir compresser n'importe quel type de référence.

J'ai une version de travail de cette compression pour les chaînes .. l'idée basée sur le post de blog de scott Hanselman http://shrinkster.com/173t

des idées pour la compression d'un objet .net?

Je sais que ce sera un cache en lecture seule puisque les objets dans le cache sera juste des tableaux d'octets ..

Répondre

20

Cela ne fonctionnera pas pour tout type de référence. Cela fonctionnera pour Serializable types. Accrochez une BinaryFormatter à un flux de compression qui est canalisé vers un fichier:

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

Vous pouvez utiliser un MemoryStream pour maintenir le contenu en mémoire, plutôt que d'écrire dans un fichier. Je doute que ce soit vraiment une solution efficace pour un cache, cependant.

+1

merci cela a été vraiment utile, à quoi ressemblerait le décompresseur ... jamais utilisé BinaryFormatter avant. –

+0

Merci d'avoir fait cela facilement copier + pastable dans mon code. Je format assez souvent les choses que c'est maintenant un extrait que je peux facilement trouver sur Google. +1 –

3

Quels types d'objets mettez-vous dans le cache? Sont-ils des objets typés? Ou des choses comme DataTable? Pour DataTable, alors peut-être stocker en tant que xml compressé par GZipStream. Pour les objets typés (entité), vous devrez probablement les sérialiser.

Vous pouvez utiliser BinaryFormatter et GZipStream, ou vous pouvez simplement utiliser quelque chose comme protobuf-net sérialisation (gratuit), qui est déjà très compacte (en ajoutant GZipStream rend généralement les données plus - ce qui est typique de binaire dense). En particulier, l'avantage de choses telles que protobuf-net est que vous obtenez la taille réduite sans avoir à payer le coût du processeur de décompression lors de la désérialisation. En some testsavant en ajoutant GZipStream, il était 4 fois plus rapide que BinaryFormatter. Ajouter le temps supplémentaire sur BinaryFormatter pour GZip et il devrait gagner par un marge considérable.

2

Je viens d'ajouter le support GZipStream pour mon application aujourd'hui, donc je peux partager du code ici;

sérialisation:

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); 
     } 
    } 
} 

Désérialisation:

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); 
     } 
    } 
} 

REMARQUE: si vous utilisez CryptoStream, il est un peu important que vous chaîne (un) passer comme un éclair et (de) crypting droit de cette façon, parce que vous voudrez perdre votre entropie avant que le cryptage ne crée du bruit à partir de vos données.

Questions connexes