2013-12-17 161 views
3

我正在創建查看器。第一次進入目錄時,通過處理文件,精確圖像和序列化數據到數據文件來創建數據文件。然後,我將該新創建的文件反序列化爲要查看的表單。第二次進入目錄時,它會看到該文件嘗試將其反序列化以填充表單。系統需要首先創建時才能正常工作,但如果已經存在,我會收到未引用的對象錯誤。我錯過了什麼?序列化 - 反序列化(二進制)

private void treeView1_NodeMouseClick(object sender, TreeNodeMouseClickEventArgs e) 
     { 
      listView1.Items.Clear(); 
      fileInfoList.Clear(); 
      //fileNameList.Clear(); 
      ClearFlowPanel(); 

      TreeNode newSelected = e.Node; 
      DirectoryInfo nodeDirInfo = (DirectoryInfo)newSelected.Tag; 

      dirPath = nodeDirInfo.FullName; 
      label_selectedPath.Text = dirPath; 

      foreach (FileInfo file in nodeDirInfo.GetFiles("*.sbs", option)) 
      { 
       if (file.Extension == ".sbs") 
       { 
        fileInfoList.Add(file); 

       } 
      } 

      foreach (FileInfo info in fileInfoList) 
      { 
       ListViewItem i = listView1.Items.Add(info.Name, 1); 
       i.SubItems.Add(SizeInKB(info.Length)); 
       i.SubItems.Add(info.LastWriteTime.ToShortDateString()); 
      } 
      listView1.AutoResizeColumns(ColumnHeaderAutoResizeStyle.HeaderSize); 

      string binData = dirPath + "\\" + ".browser" + "\\" + "_browser.bin"; 
      if (File.Exists(binData)) 
      { 
       DeserializeData(binData); //creates error 
      } 
     } 

     private void DeserializeData(string binPath) 
     { 
      FileStream fs = new FileStream(binPath, FileMode.Open); 
      BinaryFormatter bin = new BinaryFormatter(); 

      int length = (int)bin.Deserialize(fs); 

      MessageBox.Show(length.ToString()); 

      for (int i = 0; i < length; i++) 
      { 
       viewerData[i] = (ViewerData)bin.Deserialize(fs); //problem 
      } 

      for (int i = 0; i < viewerData.Length; i++) 
      { 
       PopulateFlowControl(viewerData[i]); 
       viewerNameList.Add(viewerData[i].name); 
      } 
     } 

     private void UpdateDirectory() 
     { 
      thumbPath = dirPath + "\\" + ".browser"; 
      if (!Directory.Exists(thumbPath)) 
      { 
       Directory.CreateDirectory(thumbPath); 
      } 

      fileInfoArray = fileInfoList.ToArray(); 
      viewerData = new ViewerData[fileInfoArray.Length]; 

      string binData = thumbPath + "\\" + "_browser.bin"; 
      Stream stream = File.Open(binData, FileMode.Create); 
      BinaryFormatter bin = new BinaryFormatter(); 
      bin.Serialize(stream, fileInfoArray.Length); 

      ProgressBar_Form progressBar = new ProgressBar_Form(fileInfoArray.Length); 
      progressBar.Show(); 

      for (int i = 0; i < fileInfoArray.Length; i++) 
      { 
       viewerData[i] = new ViewerData(fileInfoArray[i]); 
       bin.Serialize(stream, viewerData[i]); 

       progressBar.progressBar1.PerformStep(); 
       progressBar.label_progress.Text = "Processing : " + fileInfoArray[i].Name; 

       viewerData[i].image.Dispose(); 

       if (File.Exists(viewerData[i].imagePath)) 
       { 
        File.Delete(viewerData[i].imagePath); 
       } 
      } 

      stream.Close(); 
      progressBar.Close(); 

      DeserializeData(binData); //works fine 
     } 

編輯:

錯誤:未設置爲一個對象的實例對象引用 - 在線路在第一在DeserializeData(串binPath)評論「問題」 for循環;

堆棧跟蹤......在X

在Substance_Browser_12.Form1.DeserializeData(字符串binPath):\ Visual Studio 2010的\項目\物質設計師\ Substance_Browser_12 \ Substance_Browser_12 \ Form1.cs中:在Substance_Browser_12線151 。 Form1.treeView1_NodeMouseClick(Object sender,TreeNodeMouseClickEventArgs e)in X:\ Visual Studio 2010 \ Projects \ Substance Designer \ Substance_Browser_12 \ Substance_Browser_12 \ Form1.cs:line 133 at System.Windows.Forms.TreeView.OnNodeMouseClick(TreeNodeMouseClickEventArgs e) at System.Windows.Forms.TreeView.WmNotify(Message & m) at System.Windows.Forms.TreeView.WndProc(Message &米) 在System.Windows.Forms.Control.ControlNativeWindow.OnMessage(消息&米) 在System.Windows.Forms.Control.ControlNativeWindow.WndProc(消息&米) 在System.Windows.Forms.NativeWindow.DebuggableCallback (IntPtr hWnd,Int32 msg,IntPtr wparam,IntPtr lparam) at System.Windows.Forms.UnsafeNativeMethods.SendMessage(HandleRef hWnd,Int32 msg,IntPtr wParam,IntPtr lParam)在System.Windows.Forms.Control.SendMessage(Int32 MSG,IntPtr的WPARAM,IntPtr的LPARAM) 在System.Windows.Forms.Control.ReflectMessageInternal(IntPtr的的HWND,消息&米) 在System.Windows.Forms.Control.WmNotify(消息&米) 一個噸System.Windows.Forms.Control.WndProc(消息&米) 在System.Windows.Forms.ScrollableControl.WndProc(消息&米) 在System.Windows.Forms.Control.ControlNativeWindow.OnMessage(消息&米) 在System.Windows.Forms.Control.ControlNativeWindow.WndProc(消息&米) 在System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr的的HWND,MSG的Int32,IntPtr的WPARAM,IntPtr的LPARAM) 在System.Windows.Forms.UnsafeNativeMethods .CallWindowProc(IntPtr wndProc,IntPtr hWnd,Int32 msg,IntPtr wParam,IntPtr lParam) at System.Windows.Forms.NativeWindow.DefWndProc(Message & m) at System.Windows.Forms.Control.DefWndProc(Message &米) 在System.Windows.Forms.TreeView.WmMouseDown(消息&米,MouseButtons按鈕,點擊的Int32) 在System.Windows.Forms.TreeView.WndProc(消息&米) 在System.Windows.Forms.Control的.ControlNativeWindow.OnMessage(消息&米) 在System.Windows.Forms.Control.ControlNativeWindow.WndProc(消息&米) 在System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr的的HWND,MSG的Int32,IntPtr的WPARAM,IntPtr的LPARAM ) at System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG & msg) at System.Windows。Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(IntPtr dwComponentID,Int32 reason,Int32 pvLoopData) at System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason,ApplicationContext context) at System .Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason,ApplicationContext context) at System.Windows.Forms.Application.Run(Form mainForm) at Substance_Browser_12.Program.Main()in X:\ Visual Studio 2010 \ Projects \ Substance Designer \ Substance_Browser_12 \ Substance_Browser_12 \ Program.cs:line 18 at System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly,String [] args) at System.AppDomain.ExecuteAssembly(String assemblyFile,Evidence assemblySecurity,String [] args) 在 Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly() 在System.Threading.ThreadHelper.ThreadStart_Context(對象狀態) 在System.Threading.ExecutionContext.RunInternal(ExecutionContext中的ExecutionContext,ContextCallback回調,對象狀態,布爾preserveSyncCtx) 的系統。 Threading.ExecutionContext.Run(的ExecutionContext的ExecutionContext,ContextCallback回調,對象的狀態,布爾preserveSyncCtx) 在System.Threading.ExecutionContext.Run(的ExecutionContext的ExecutionContext,ContextCallback回調,對象狀態) 在System.Threading.ThreadHelper.ThreadStart()

+1

在哪一行你會得到未引用的對象錯誤? – paqogomez

+0

你能提供錯誤信息和堆棧跟蹤嗎? – Grundy

+0

感謝您添加實際的例外文本。 「未設置對象實例的對象引用」與「未引用的對象錯誤」並不等同,這是誤導。 – groverboy

回答

0

in msdn BinaryFormatter.Deserialize Method (Stream)

For successful deserialization, the current position in the stream must be at the beginning of the object graph.

因此可能當您嘗試反序列化流中的當前位置時不在對象圖的開頭。

0

你只需要改變這個

private void DeserializeData(string binPath) 
    { 
     FileStream fs = new FileStream(binPath, FileMode.Open); 
 fs.Seek(0, SeekOrigin.Begin); 
 BinaryFormatter bin = new BinaryFormatter(); 

     int length = (int)bin.Deserialize(fs); 

     MessageBox.Show(length.ToString()); 

     for (int i = 0; i < length; i++) 
     { 
      viewerData[i] = (ViewerData)bin.Deserialize(fs); //problem 
     } 

     for (int i = 0; i < viewerData.Length; i++) 
     { 
      PopulateFlowControl(viewerData[i]); 
      viewerNameList.Add(viewerData[i].name); 
     } 
    } 

OR

public static System.IO.MemoryStream Serialize(object _Object) 
{ 
    System.IO.MemoryStream _Return = new System.IO.MemoryStream(); 
    Serialize(ref _Return, _Object); 
    return _Return; 
} 

public static void Serialize(ref System.IO.Stream Stream, object _Object) 
{ 
    BinaryFormatter BF = new BinaryFormatter(); 
    BF.Serialize(Stream, _Object); 
} 

public static objType Deserialize<objType>(ref System.IO.Stream Stream) 
{ 
    object _Return = null; 
    Stream.Seek(0, SeekOrigin.Begin); 
    BinaryFormatter BF = new BinaryFormatter(); 
    _Return = BF.Deserialize(Stream); 
    return (objType)_Return; 
} 
+0

我試過添加這一行,我收到了同樣的錯誤。 – topofsteel

0

您正在連載多個ViewerData對象到一個文件,但有在這些對象沒有容器文件。我不認爲BinaryFormatter支持這種用法。這些對象序列化的替代方法:

  • 爲每個文件序列化一個ViewerData。
  • 將所有ViewerData對象添加到集合,然後將集合序列化。如果存在許多大圖像,則可能會出現內存不足錯誤。
  • 開發一種將BinaryFormatter與手動寫入/讀取相結合的算法,以避免使用過多的內存。這可能需要一箇中間流,例如,用於序列化每個ViewerData的MemoryStream。請參閱下面的僞代碼步驟。

將對象寫入文件流的次數。
對於每個對象。 使用BinaryFormatter對MemoryStream進行序列化。 將MemoryStream的長度寫入文件流。 將MemoryStream寫入文件流

然後對反序列化對象做相反處理。

+0

我的印象是數組是容器。請注意,當我最初創建數據文件然後將其反序列化時,它工作正常。在這兩種情況下,我都會調用完全相同的DeserializeData方法。 – topofsteel

+0

@topofsteel - 不,您正在序列化ViewerData對象和一個整數,而不是它們的數組。順便說一句,感謝您發佈您的答案,有趣的是知道BinaryFormatter的工作原理是這樣的,即反序列化隻影響流中的下一個對象(int,ViewerData)。然而,這是我不推薦依賴的無證行爲。 – groverboy

+0

更多關於這個未公開的行爲[嘗試反序列化多個對象在同一時間](http://stackoverflow.com/questions/13787723/trying-to-deserialize-more-than-1-object-at-the - 同時/ 13790222#13790222)和 [反序列化特定對象](http://stackoverflow.com/a/18383530/1015802)。 – groverboy

0

我需要在DeserializeData(string binPath)中重新初始化viewerData。如果它來自UpdateDirectory()它已經是。

viewerData = new ViewerData[length]; 

謝謝大家的意見!

相關問題