2009-08-27 21 views
7

Cuando .NET se usa BinaryFormatter para serializar un gráfico de objetos, ¿se aplica algún tipo de compresión?¿BinaryFormatter aplica compresión?

Pregunto en el contexto de si debería preocuparme si el gráfico objeto tiene muchas cadenas y números enteros repetidos.

Editar - Espere, si las cadenas están internados en .NET, no hay necesidad de preocuparse por las cadenas repetidas, ¿verdad?

+0

Los primitivos se repiten felizmente hasta la saciedad, la única "compresión" que se produce es que las secuencias ininterrumpidas de nulos (por ejemplo, en una matriz) se almacenan como bytes o enteros que representan el número en la secuencia. Las cadenas (generalmente) no se repiten, las definiciones de clase no se repiten y las referencias a múltiples objetos no dan como resultado que el objeto se serialice/envíe varias veces. – Tao

Respuesta

10

No, no proporciona ninguna compresión, pero puede comprimir la salida usted mismo utilizando el tipo GZipStream.

Editar:Mehrdad tiene un maravilloso ejemplo de esta técnica en su respuesta a How to compress a .net object instance using gzip.

Edición 2: Cuerdas pueden ser internados, pero eso no quiere decir que cada cadena es internados. No haría ninguna suposición sobre cómo o por qué el CLR decide internar cadenas, ya que esto puede cambiar (y ha cambiado) de una versión a otra.

4

No, no lo hace, pero ...

Acabo de añadir soporte GZipStream para mi aplicación hoy en día, para poder compartir algo de código aquí;

serialización:

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

Deserialización:

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: si utiliza CryptoStream, es poco importante que la cadena de (des) compresión y (de) crypting derecha de esta manera, porque querrás perder tu entropía ANTES de que el cifrado genere ruido a partir de tus datos.