2011-11-13 34 views
4

反序列化,我有以下问题:当我开始我的应用程序,设置从文件加载的,所以反序列化,当这发生了,我得到了以下错误:“分析完成前遇到的流结束。”当从文件

{"End of Stream encountered before parsing was completed."} System.Exception {System.Runtime.Serialization.SerializationException}

序列化代码:

using(FileStream write = new FileStream(SETTINGSPATH,FileMode.Create,FileAccess.Write) 
{ 
    BinaryFormatter formatter = new BinaryFormatter(); 
    formatter.Serialize(write,settings); 
} 

Deserialisation方法:

using (FileStream read = new FileStream(SETTINGSPATH,FileMode.Open,FileAccess.Read)) 
{ 
    BinaryFormatter formatter = new BinaryFormatter(); 
    read.Position = 0; 
    settings = (Settings)formatter.Deserialize(read); // settings is declared as Settings object 
} 

设置类:

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Runtime.Serialization; 
using System.Text; 

namespace Serie_Counter.Overkoepelend 
{ 
public delegate void SelectedMoveOptionChanged(AutoMoveOption selectedOption, int checkInterval = 30); 

public delegate void EnableAutoMoveChanged(bool EnableAutoMove); 

[Serializable] 
public class Settings 
{ 
    private string serieListSavePath; 
    private bool autoStart; 
    private bool enableRember; 
    private bool closeWithMainForm; 
    private int warningDelay; 
    // moving options 
    private bool enableAutoMove; 
    private string rootFolder; 
    private int checkInterval; 
    private AutoMoveOption selectedMoveOption; 

    public event SelectedMoveOptionChanged selectedMoveOptionChanged; 
    public event EnableAutoMoveChanged enableAutoMoveChanged; 

    #region Properties 

    public string SerieListSavePath 
    { 
     get 
     { 
      return serieListSavePath; 
     } 
     set 
     { 
      serieListSavePath = value; 
     } 
    } 

    public bool AutoStart 
    { 
     get 
     { 
      return autoStart; 
     } 
     set 
     { 
      autoStart = value; 
     } 
    } 

    public bool EnableRember 
    { 
     get 
     { 
      return enableRember; 
     } 
     set 
     { 
      enableRember = value; 
     } 
    } 

    public bool CloseWithMainForm 
    { 
     get 
     { 
      return closeWithMainForm; 
     } 
     set 
     { 
      closeWithMainForm = value; 
     } 
    } 

    public int WarningDelay 
    { 
     get 
     { 
      return warningDelay; 
     } 
     set 
     { 
      warningDelay = value; 
     } 
    } 

    public bool EnableAutoMove 
    { 
     get 
     { 
      return enableAutoMove; 
     } 
     set 
     { 
      enableAutoMove = value; 
      if (enableAutoMove != null) enableAutoMoveChanged(value); 
     } 
    } 

    public string RootFolder 
    { 
     get 
     { 
      return rootFolder; 
     } 
     set 
     { 
      rootFolder = value; 
     } 
    } 

    public int CheckInterval 
    { 
     get 
     { 
      return checkInterval; 
     } 
     set 
     { 
      checkInterval = value; 
     } 
    } 

    public AutoMoveOption SelectedMoveOption 
    { 
     get 
     { 
      return selectedMoveOption; 
     } 
     set 
     { 
      selectedMoveOption = value; 
      selectedMoveOptionChanged(value, checkInterval); 

     } 
    } 

    #endregion 



    public Settings(string serieListSavePath) 
    { 
     this.serieListSavePath = serieListSavePath; 
    } 

    public Settings() 
    { 
     this.serieListSavePath = "series.xml"; 
     warningDelay = -1; 
    } 

    [OnDeserialized] 
    private void SetValuesOnDeserialized(StreamingContext context) 
    { 
     selectedMoveOptionChanged = null; 
     enableAutoMoveChanged = null; 

    } 

有没有人知道为什么会发生这种情况?

如果您想了解更多信息或代码请http://seriescounter.codeplex.com/

电贺 托马斯

编辑:难道这个问题是因为我的序列事件,反序列化失败? 我只是测试了这一点,确保序列化时事件为空。到目前为止,错误不再发生。

http://seriescounter.codeplex.com/SourceControl/changeset/changes/12646

+0

您是否检查文件是否存在并且未损坏? – Vlad

+0

如果你只是一个存储设置,那么经验法则是使用可读的格式,比如XML来保存设置。 –

+0

请发布您用于序列化和保存设置的代码。在您发布的codeplex链接中找到并不容易。我怀疑它可能缺少一个'Flush'。另外,你没有正确地触发'enableAutoMoveChanged'事件。你应该首先将事件复制到局部变量'var ev = enableAutoMoveChanged;'然后检查'ev'是否为空,然后触发'ev(value);' – spender

回答

6

更改设置12594是你的问题,你添加checkIntervalChanged事件设置类。这样就会为序列化的类添加一个不可见的字段。但是,现在您在设置使用先前版本保存的文件时遇到问题,序列化数据不包含该字段,结果就是例外。

你可以拯救它是这样的:

[Serializable] 
    public class Settings { 
     [NonSerialized] 
     private CheckIntervalChanged checkIntervalChangedBacking; 

     public event CheckIntervalChanged CheckIntervalChanged { 
      add { checkIntervalChangedBacking += value; } 
      remove { checkIntervalChangedBacking -= value; } 
     } 
     // etc.. 
    } 

的[非序列化]属性现在可以确保支持字段没有被序列化。无论如何你永远都不想序列化事件。

一般来说,你需要小心二进制序列化,版本控制很难处理。添加一个字段可以并将立即将任何存储的数据转换为垃圾。 MSDN库中的“Version tolerant serialization”部分有很好的提示。

+0

向类中添加字段不应影响从旧版本开始的反序列化,因为未知字段将仅填充其默认值。另外,通过使用属性的字段说明符不能序列化事件,即事件声明中的[field:NonSerialized]。 – tyranid

+1

我得到了同样的错误,发现这个页面。但是,我的问题是,事实证明,我添加了一个新类,并忘记将[Serializable]属性添加到类中,以便它无法正确序列化。然后,当它试图反序列化时,我得到了这个错误。一旦将[Serializable]属性添加到类中,一切正常。 – newman

相关问题