Pregunta

Estoy tratando de hacer serialización personalizada / deserialización de un objeto, así como la compresión / descompresión de los datos serializados con DeflateStreams. Originalmente hice esto para objetos más complejos, pero Córtala a tratar de averiguar el problema, sin embargo, solo se hizo más desconcertante, ya que todavía está allí. Aquí está la clase para serializar / deserializar:

[Serializable]
    public class RandomObject : ISerializable
    {
        public String Name { get; set; }
        public String SavePath { get; set; }

        public RandomObject()
        {
        }

        public RandomObject(String name, String savepath)
        {
            Name = name;
            SavePath = savepath;
        }

        public RandomObject(SerializationInfo info, StreamingContext context)
            : this(info.GetString("name"), info.GetString("savepath"))
        {
        }
        [SecurityPermissionAttribute(SecurityAction.Demand, SerializationFormatter = true)]
        public void GetObjectData(SerializationInfo info, StreamingContext context)
        {
            info.AddValue("name", Name);
            info.AddValue("savepath", SavePath);
        }
    }

Y aquí está el código que se supone que serializarlo (que parece el trabajo):

BinaryFormatter bf = new BinaryFormatter();
            using (MemoryStream ms = new MemoryStream())
            {
                bf.Serialize(ms, profile);
                using (DeflateStream ds = new DeflateStream(ms, CompressionMode.Compress))
                {
                    try
                    {
                        using (FileStream fs = File.Create(path))
                        {
                            ds.Flush();
                            Miscellaneous.CopyStream(ds.BaseStream, fs);
                            fs.Flush();
                            fs.Close();
                        }
                    }
                    catch (IOException e)
                    {
                        MessageBox.Show(e.Message);
                        success = false;
                    }
                    ds.Close();
                }
                ms.Close();
            }

Y aquí está la deserialización:

RandomObject profile = null;
                using (FileStream fs = File.OpenRead(path))
                {
                    using (DeflateStream ds = new DeflateStream(fs, CompressionMode.Decompress))
                    {
                        BinaryFormatter bf = new BinaryFormatter();
                        ds.Flush();

                        using (MemoryStream ms = new MemoryStream())
                        {
                            Miscellaneous.CopyStream(ds.BaseStream, ms);
                            profile = bf.Deserialize(ms) as RandomObject;
                            profile.SavePath = path;
                            ms.Close();
                        }
                        ds.Close();
                    }
                    fs.Close();
                }

Ahora, con el problema. Deserialización arroja una SerializationException con el mensaje { "No hay ningún mapa para el objeto '201326592'."} No tengo ni idea de cómo solucionar o averiguar qué es exactamente la causa del problema. serialización muy básico funciona cuando acabo de correr métodos serializar y deserializar de BinaryFormatter en el mismo MemoryStream.

He intentado eliminar la materia DeflateStream de ambos métodos, pero sigue siendo el mismo problema. Cuando miro a los ejemplos de MSDN y otros lugares parece que lo estoy haciendo justo, y buscando en Google para el mensaje de excepción no da ningún resultado significativo (o tal vez sólo soy malo en la búsqueda).

PS. Como se puede ver que uso Miscellaneous.CopyStream (src, dest), que es una copiadora básica corriente, ya que no puedo conseguir src.CopyTo (dest) para trabajo en absoluto, por lo que ninguna pista sobre que es bienvenido también.

A continuación se muestra un enlace a todo el proyecto VS2010 si le gustaría ver más de cerca: http://www.diredumplings.com/SerializationTesting.zip

ACTUALIZACIÓN:

The_Smallest : He intentado utilizar el método Comprimir informados sobre mi serialización:

BinaryFormatter bf = new BinaryFormatter();
            using (MemoryStream stream = new MemoryStream())
            {
                bf.Serialize(stream, profile);

                byte[] array = Compress(stream);

                using (MemoryStream ms = new MemoryStream(array))
                {
                    using (FileStream fs = File.Create(path))
                    {
                        ms.WriteTo(fs);
                        fs.Flush();
                    }
                }
            }

Sin embargo, me parece dar los mismos problemas que tuve con srcStream.CopyTo (destStream) anterior, que es que no parece que se escribe en la secuencia. El resultado es un archivo 0 kb cuando trato de guardarlo en el disco. Algunas ideas?

Pieter : He quitado la MemoryStream del método deserialización y parece tener la misma funcionalidad que antes. Sin embargo no estoy seguro de cómo implementar la serialización de la manera que usted sugiere. Es esto lo que tenías en mente?

BinaryFormatter bf = new BinaryFormatter();

            using (FileStream fs = File.Create(path))
            {
                using (DeflateStream ds = new DeflateStream(fs, CompressionMode.Compress))
                {
                    bf.Serialize(ds, profile);
                    fs.Flush();
                    ds.Close();
                }
                fs.Close();
            }

Gracias a los dos!

¿Fue útil?

Solución

Te dowloaded ejemplo y cavó un poco de allí. Ver cambios para su proyecto a continuación:

  1. Reemplazar LoadFromFile en Loader.cs
private static RandomObject LoadFromFile(string path)
{
  try
  {
    var bf = new BinaryFormatter();
    using (var fileStream = File.OpenRead(path))
    using (var decompressed = new MemoryStream())
    {
      using (var deflateStream = new DeflateStream(fileStream, CompressionMode.Decompress))
        deflateStream.CopyTo(decompressed);

      decompressed.Seek(0, SeekOrigin.Begin);
      var profile = (RandomObject)bf.Deserialize(decompressed);
      profile.SavePath = path;
      return profile;
    }
  }
  catch (IOException e)
  {
    MessageBox.Show(e.Message);
    return null;
  }
}

  1. Reemplazar Save en Saver.cs como sigue:
public static bool Save(RandomObject profile, String path)
{
   try
   {
      var bf = new BinaryFormatter();
      using (var uncompressed = new MemoryStream())
      using (var fileStream = File.Create(path))
      {
         bf.Serialize(uncompressed, profile);
         uncompressed.Seek(0, SeekOrigin.Begin);

         using (var deflateStream = new DeflateStream(fileStream, CompressionMode.Compress))
           uncompressed.CopyTo(deflateStream);
      }
      return true;
    }
    catch (IOException e)
    {
       MessageBox.Show(e.Message);
       return false;
    }
}

Otros consejos

debe serializar en el DeflateStream, no la base (MemoryStream) corriente.

Para la serialización: comienzan con la File.Create. Luego, alrededor de esa corriente, crear el DeflateStream. A continuación, a la DefaulteStream, serializar los objetos.

Para deserializar:. No cree el MemoryStream y deserializar directamente desde el DeflateStream

Creo que no hay necesidad de que el MemoryStream añadido. Sin embargo, si usted tiene problemas para escribir directamente al / la lectura directa de las secuencias de archivo, basta con cambiar la rutina serializar escribir en el DeflateStream en lugar de la MemoryStream.

Esto debería resolver sus problemas.

No hay error en arroyos lógicas, mientras que la compresión se debe escribir en CompressStream, que escribe a MemoryStream, después de esto tendrá resultado en MemoryStream (no en CompressStream) Aquí es un ejemplo de cómo comprimir y descomprimir bytes

    private static byte[] Compress(Stream stream)
    {
        using (var resultStream = new MemoryStream())
        {
            using (var gzipStream = new DeflateStream(resultStream, CompressionMode.Compress))
                stream.CopyTo(gzipStream);
            return resultStream.ToArray();
        }
    }

    private static byte[] Decompress(byte[] bytes)
    {
        using (var readStream = new MemoryStream(bytes))
        using (var resultStream = new MemoryStream())
        {
            using (var gzipStream = new DeflateStream(readStream, CompressionMode.Decompress))
                gzipStream.CopyTo(resultStream);
            return resultStream.ToArray();
        }
    }
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top