2014-02-27 344 views
1

我試圖使用BinaryFormatter序列化我正在開發的程序的狀態,但是當我試圖反序列化生成的文件時,出現以下錯誤。我的代碼檢查,以確保文件名是有效的(已補充說,看到這裏很多類似的問題之後),所以我不理解這個錯誤是如何發生的:爲什麼產生「空路徑名稱不合法」例外?

System.ArgumentException
Message=Empty path name is not legal.
Source=mscorlib
StackTrace:
at System.IO.FileStream.Init(String path, FileMode mode, FileAccess access, Int32 rights, Boolean useRights, FileShare share, Int32 bufferSize, FileOptions options, SECURITY_ATTRIBUTES secAttrs, String msgPath, Boolean bFromProxy, Boolean useLongPath)
at System.IO.FileStream..ctor(String path, FileMode mode, FileAccess access, FileShare share)
at System.Windows.Media.Imaging.BitmapDecoder.SetupDecoderFromUriOrStream(Uri uri, Stream stream, BitmapCacheOption cacheOption, Guid& clsId, Boolean& isOriginalWritable, Stream& uriStream, UnmanagedMemoryStream& unmanagedMemoryStream, SafeFileHandle& safeFilehandle)
at System.Windows.Media.Imaging.BitmapDecoder.CreateFromUriOrStream(Uri baseUri, Uri uri, Stream stream, BitmapCreateOptions createOptions, BitmapCacheOption cacheOption, RequestCachePolicy uriCachePolicy, Boolean insertInDecoderCache)
at System.Windows.Media.Imaging.BitmapImage.FinalizeCreation()
at System.Windows.Media.Imaging.BitmapImage.EndInit()
at StarShips.Ship..ctor(SerializationInfo info, StreamingContext ctxt) in C:\Projects\Dalek\StarShips\Ship.cs:line 387

這裏是我的保存方法,其最初創建文件:

Microsoft.Win32.SaveFileDialog sfd = new Microsoft.Win32.SaveFileDialog(); 
sfd.FileName = "NewGame"; 
sfd.DefaultExt = ".sav"; 
sfd.Filter = "Save Games (.sav)|*.sav"; 
Nullable<bool> result = sfd.ShowDialog(); 
if (result == true) 
{ 
    string fileName = sfd.FileName; 
    IFormatter formatter = new BinaryFormatter(); 
    Stream stream = new FileStream(fileName, FileMode.Create, FileAccess.Write, FileShare.None); 
    GameTest t = new GameTest(); 
    t.Players = GameState.Players; 
    formatter.Serialize(stream, t); 

    MessageBox.Show(string.Format("Save Complete! Size: {0}",stream.Length)); 
    stream.Close(); 
} 

及這裏的拋出異常的代碼:

Microsoft.Win32.OpenFileDialog ofd = new Microsoft.Win32.OpenFileDialog(); 
ofd.FileName = "NewGame"; 
ofd.DefaultExt = ".sav"; 
ofd.Filter = "Save Games (.sav)|*.sav"; 
Nullable<bool> result = ofd.ShowDialog(); 
if (result == true) 
{ 
    string fileName = ofd.FileName; 
    System.Diagnostics.Debug.WriteLine(fileName); 
    IFormatter formatter = new BinaryFormatter(); 
    Stream stream = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read); 
    stream.Position = 0; 
    MessageBox.Show(string.Format("size: {0}, Filename: {1}", stream.Length,((FileStream)stream).Name)); 
    GameTest t = (GameTest)formatter.Deserialize(stream); // Error occurs here 
    stream.Close(); 
} 

我從幾乎無處不在我的文件系統試圖保存/載入至/,前前後後m C驅動器的根目錄,甚至在程序的執行文件夾中。
我試過進入Deserialize,它遍歷了大量的對象圖形,但之後突然回到我上面的Deserialize調用並引發異常。
在我的反序列化之前的消息框顯示流的文件名是有效的,那麼爲什麼我會得到這個消息?

編輯:如果我在調試過程中繼續經過錯誤,會出現另一個錯誤:「解析完成之前遇到的流結束。我仔細檢查了所有的類,並且所有的GetObjectData方法都添加了Serialization構造函數的相同值,所以我不知道它在流之外的位置。

+1

您有文件名,但實際路徑在哪裏? – aw04

+0

FileName包括完整路徑,例如「C:\ NewGame.sav」。據我所知,這是基本序列化的MSDN文章如何處理這個問題,並且在拋出錯誤之前,反序列化可以通過大部分對象圖。 –

+0

爲什麼使用Win32.OpenFileDialog而不是Forms.OpenFileDialog?也許在返回的路徑中存在一些不兼容性? –

回答

5

at StarShips.Ship..ctor(SerializationInfo info, StreamingContext ctxt)

異常的調用堆棧顯示您正在尋找這個問題的完全錯誤的角落。您認爲它是包含錯誤的序列化數據的文件路徑,堆棧跟蹤講述了一個非常不同的故事。

如果容易混淆,.ctor是類的構造函數的內部CLR名稱。所以它實際上是你的Ship類構造函數的炸彈。它試圖用BitmapImage(Uri)構造函數創建一個BitmapImage對象。這是構造函數的問題。可能是因爲你忘記了序列化位圖的文件名,或者沒有正確處理這個字符串爲空或空。

在Ship構造函數上放置一個斷點以單步執行代碼。或者使用Debug + Exceptions,勾選Thrown複選框以獲得CLR異常,以便在拋出異常時停止調試器。或者刪除代碼中的try/catch來吞噬異常,這會影響診斷問題。

+0

啊哈!我專注於頂部而錯過了那部分。注意自我:下次讀取整個堆棧跟蹤。 –