2010-11-28 126 views
5

我正在尝试执行对象的自定义序列化/反序列化以及使用DeflateStreams压缩/解压缩序列化的数据。我原本是为了处理更复杂的对象而做的,但是为了试图找出问题而做了一些尝试,但是由于它仍然存在,它变得更加令人费解。这里是要序列化的类/反序列化:C#自定义序列化/反序列化与DeflateStreams

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

这里是应该序列化(这似乎工作)代码:

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

,这里是反序列化:

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

现在,解决问题。反序列化抛出一个SerializationException,并带有消息{“No map for object'201326592'。”}我不知道如何解决问题或弄清究竟是什么导致了问题。当我在同一个MemoryStream上运行BinaryFormatter的Serialize和Deserialize方法时,非常基本的序列化工作。

我试图从两种方法中删除DeflateStream的东西,但它仍然是同样的问题。当我看到MSDN和其他地方的示例时,它看起来像我做得很恰当,并且使用Google搜寻异常消息不会给出任何有意义的结果(或者我可能只是在搜索时遇到不好的情况)。

PS。正如你所看到的,我使用Miscellaneous.CopyStream(src,dest),它是一个基本的流复制器,因为我无法获得src.CopyTo(dest)的功能,所以我们也欢迎任何提示。

下面是一个链接到整个VS2010项目,如果你想更仔细地看: http://www.diredumplings.com/SerializationTesting.zip

UPDATE:

The_Smallest:我试着用你贴在压缩方法我系列化:

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

然而,这似乎给我,我和srcStream.CopyTo(destStream)早前曾同样的问题,这是它似乎没有写入流中。当我尝试将它保存到磁盘时,结果是一个0 kb的文件。有任何想法吗?

Pieter:我从反序列化方法中删除了MemoryStream,它看起来具有和以前相同的功能。但是我不确定如何按照您的建议来实现序列化。这是你想到的吗?

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

感谢你们俩!

+0

什么是Stream.Copy的问题?它为什么会失败? – 2010-11-28 17:03:16

+0

无论我如何使用它,目标流总是空的,可能只是我做了一些愚蠢的事情。 – vesz 2010-11-28 18:19:14

回答

1

我下载了你的例子,并在那里挖了一点。请参阅下面的项目变化:

  1. 在Loader.cs更换LoadFromFile
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. 在Saver.cs更换Save如下:
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; 
    } 
} 
1

您应该序列化为DeflateStream,而不是基础流(MemoryStream)。

序列化:从File.Create开始。然后在该流的附近创建DeflateStream。然后到DefaulteStream,序列化你的对象。

对于反序列化:请勿创建MemoryStream并直接从DeflateStream反序列化。我相信不需要添加MemoryStream。但是,如果直接写入/直接从文件流中读取时出现问题,只需更改序列化例程以写入DeflateStream而不是MemoryStream

这应该解决您的问题。

+0

MemoryStream的原因是,因为我可以告诉我只能读取DeflateStream,而不是写入或寻找它。我会尝试上面的更改,看看它是否有效,谢谢。 – vesz 2010-11-28 17:13:17

+0

我在问题中发布了一个更新到您的解决方案,我仍然不知道如何让它工作。谢谢你的回复! – vesz 2010-11-28 18:11:03

1

有溪流中的逻辑错误,在压缩的同时,你应该写CompressStream,其中写到MemoryStream的,在这之后,你将有结果的MemoryStream(不CompressStream) 下面是例子,如何压缩和解压缩字节

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