2011-11-13 47 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

相關問題