为什么这会产生“空路径名称不合法”的例外情况?

时间:2014-02-27 22:58:13

标签: c# .net serialization

我正在尝试使用BinaryFormatter来序列化我正在开发的程序的状态,但是当我尝试反序列化生成的文件时,我收到以下错误。我的代码检查以确保文件名有效(已经在这里看到很多类似的问题后添加了),所以我不明白这个错误是如何发生的:

  

System.ArgumentException
  消息=空路径名称不合法   来源= mscorlib程序
  堆栈跟踪:
  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)
  在System.IO.FileStream..ctor(字符串路径,FileMode模式,FileAccess访问,FileShare共享)
  在System.Windows.Media.Imaging.BitmapDecoder.SetupDecoderFromUriOrStream(Uri uri,Stream stream,BitmapCacheOption cacheOption,Guid& clsId,Boolean& isOriginalWritable,Stream& uriStream,UnmanagedMemoryStream& unmanagedMemoryStream,SafeFileHandle& safeFilehandle)
  在System.Windows.Media.Imaging.BitmapDecoder.CreateFromUriOrStream(Uri baseUri,Uri uri,Stream stream,BitmapCreateOptions createOptions,BitmapCacheOption cacheOption,RequestCachePolicy uriCachePolicy,Boolean insertInDecoderCache)
  在System.Windows.Media.Imaging.BitmapImage.FinalizeCreation()
  在System.Windows.Media.Imaging.BitmapImage.EndInit()
  在StarShips.Ship..ctor(SerializationInfo info,StreamingContext ctxt)中的C:\ Projects \ Dalek \ StarShips \ Ship.cs:第387行

这是我的Save方法,它最初创建文件:

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

我尝试从文件系统的几乎所有位置,从C盘的根目录,甚至在程序的执行文件夹中保存/加载。 我已经尝试进入Deserialize,它迭代了大量的对象图,但后来突然回到我上面的Deserialize调用并抛出异常。
在反序列化之前的消息框显示流的文件名是有效的,为什么我收到此消息?

编辑:如果我在调试时继续经过错误,我会收到另一个错误:“在解析完成之前遇到了Stream of Stream。”我仔细检查了所有类,并且所有GetObjectData方法都为Serialization构造函数添加了相同的值,因此我不知道它在流中的运行位置。

1 个答案:

答案 0 :(得分:5)

  

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

异常的调用堆栈显示您正在查找此问题的完全错误的角落。您假设它是包含错误的序列化数据的文件的路径,堆栈跟踪说明了一个非常不同的故事。

如果它令人困惑,.ctor是类的构造函数的内部CLR名称。所以实际上你的Ship类构造函数就是炸弹。它尝试使用BitmapImage(Uri)构造函数创建BitmapImage对象。它是具有问题的构造函数的参数。可能是因为您忘记序列化位图的文件名或者没有正确处理此字符串为空或空。

在Ship构造函数上放置一个断点以单步执行代码。或者使用Debug + Exceptions,勾选CLR异常的Thrown复选框,以便在抛出异常时调试器停止。或者删除吞噬异常的代码中的try / catch,它会妨碍诊断问题。