2014-02-27 311 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

啊哈!我专注于顶部而错过了那部分。注意自我:下次读取整个堆栈跟踪。 –