2013-12-17 5 views
3

뷰어를 만들고 있습니다. 처음으로 디렉토리로 이동할 때, 파일을 처리하고, 이미지를 정확하게 만들고, 데이터 파일로 데이터를 직렬화하여 데이터 파일을 작성합니다. 그런 다음 새로 만든 파일을 볼 수있는 형식으로 deserialize합니다. 두 번째로 디렉토리로 이동하면 ans가 해당 파일을 deserialize하여 양식을 채 웁니다. 처음에는 시스템을 생성해야 할 때 시스템이 올바르게 작동하지만 이미 있으면 참조되지 않은 오브젝트 오류가 발생합니다. 내가 뭘 놓치고 있니?직렬화 - 비 직렬화 (이진)

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)에서 루프 먼저 '문제를'댓글을 달았습니다;

스택 추적 ... X에서 Substance_Browser_12.Form1.DeserializeData (문자열 binPath)에서

: 비주얼 스튜디오 2010 \ 프로젝트 \ \ 물질 디자이너 \ Substance_Browser_12 \ Substance_Browser_12 \ Form1.cs를 : Substance_Browser_12에서 라인 (151) . X : \ Visual Studio 2010 \ Projects \ Substance Designer \ Substance_Browser_12 \ Substance_Browser_12 \ Form1.cs의 Form1.treeView1_NodeMouseClick (개체 보낸 사람, TreeNodeMouseClickEventArgs e) : System.Windows.Forms.TreeView.OnNodeMouseClick (TreeNodeMouseClickEventArgs e)의 줄 at 줄 System.Windows.Forms.TreeView.WmNotify (메시지 &m) at System.Windows.Forms.TreeView.WndProc (메시지m) System.Windows.Forms.Control.ControlNativeWindow.OnMessage (메시지 & m) System.Windows.Forms.Control.ControlNativeWindow.WndProc에서 (메시지 & m) 에서 System.Windows.Forms.NativeWindow.DebuggableCallback에서 (HandleRef hWnd, Int32 msg, IntPtr wParam, IntPtr lParam) 에서 System.Windows.Forms.Control.SendMessage (Int32, Int32 msg, IntPtr 매개 변수, IntPtr 매개 변수) System.Windows.Forms.Control.WmNotify에서 System.Windows.Forms.Control.ReflectMessageInternal (HWND를 IntPtr, 메시지 & m) 에서 MSG,을 IntPtr의 WPARAM, LPARAM을 IntPtr의) (메시지 & m) System.Windows.Forms.Control.ControlNativeWindow.OnMessage (메시지 & m) 에서 System.Windows.Forms.ScrollableControl.WndProc (메시지 & m)에서 t System.Windows.Forms.Control.WndProc (메시지 & m) System.Windows.Forms.Control.ControlNativeWindow.WndProc (Message &m)에서 (System.Windows.Forms.NnsWebModel) System.Windows.Forms.Control.DefWndProc에서 System.Windows.Forms.NativeWindow.DefWndProc (메시지 & m) 에서 .CallWindowProc (WNDPROC을 IntPtr, HWND를 IntPtr, INT32의 MSG,을 IntPtr의 wParam,을 IntPtr의 lParam) (메시지 0,123,224 System.Windows.Forms.Control에서 System.Windows.Forms.TreeView.WndProc (메시지 & m) 에서 9,미터) System.Windows.Forms.TreeView.WmMouseDown에서 & m은 MouseButtons 버튼, INT32 클릭 수 (메시지) .ControlNativeWindow.OnMessage (메시지 & m) System.Windows.Forms.NativeWindow.DebuggableCallback에서 System.Windows.Forms.Control.ControlNativeWindow.WndProc (메시지 & m) 에서 (HWND를 IntPtr, INT32의 MSG,을 IntPtr의 WPARAM, LPARAM을 IntPtr의) at System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW (MSG & msg) at System.Windows.System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner (Int32 이유, ApplicationContext 컨텍스트)의 에서 (시스템의 경우) 시스템에서 을 입력하십시오. Forms.Application.ComponentManager.System.Windows. .Windows.Forms.Application.ThreadContext.RunMessageLoop (Int32 reason, ApplicationContext context) at System.Windows.Forms.Application.Run (양식 mainForm) at Substance_Browser_12.Program.Main() in X : \ Visual Studio 2010 \ Projects System.AppDomain.ExecuteAssembly (String assemblyFile, Evidence assemblySecurity, String [] args)의 (System.AppDomain._nExecuteAssembly에서 (런타임 어셈블리 어셈블리, 문자열 [] args) 에서 System.AppDomain.ExecuteAssembly ~에서 Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly() 시스템에서 System.Threading.ExecutionContext.RunInternal에서 System.Threading.ThreadHelper.ThreadStart_Context (개체 상태) (의 ExecutionContext의 ExecutionContext, ContextCallback 콜백, 부울 preserveSyncCtx을 상태 개체) 에서 . Threading.ExecutionContext.Run (ExecutionContext에 ExecutionContext에, ContextCallback 콜백, 객체 상태 부울 preserveSyncCtx) System.Threading.ThreadHelper.ThreadStart에서 System.Threading.ExecutionContext.Run (ExecutionContext에 ExecutionContext에, ContextCallback 콜백, 객체 상태)에서 ()

+1

참조되지 않은 개체 오류가 발생한 줄은 무엇입니까? – paqogomez

+0

오류 메시지와 스택 추적을 제공 할 수 있습니까? – Grundy

+0

실제 예외 텍스트를 추가해 주셔서 감사합니다. "개체 참조가 개체의 인스턴스로 설정되지 않았습니다"는 "참조되지 않은 개체 오류"와 같은 의미는 아닙니다. 오해의 소지가 있습니다. – groverboy

답변

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

또는

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 하나 개의 파일에 객체 만에서 이러한 개체에 대한 컨테이너가 없습니다 serialising된다 파일. 나는 BinaryFormatter이이 사용법을 지원한다고 생각하지 않는다. 이러한 객체를 직렬화하는 다른 방법은 다음과 같습니다.

  • 파일 당 하나의 ViewerData를 직렬화하십시오.
  • 모든 ViewerData 개체를 컬렉션에 추가 한 다음 컬렉션을 serialize합니다. 큰 이미지가 많은 경우이 방법으로 메모리 오류가 발생할 수 있습니다.
  • 과도한 메모리 사용을 피하기 위해 BinaryFormatter과 수동 쓰기/읽기를 결합한 알고리즘을 개발하십시오. 아마도 중간 스트림이 필요합니다. 각 ViewerData를 serialize하기위한 MemoryStream. 아래 의사 코드 단계를 참조하십시오.

파일 스트림에 개체의 개수를 씁니다.
각 개체에 대해. BinaryFormatter에서 MemoryStream으로 직렬화합니다. MemoryStream의 길이를 파일 스트림에 씁니다. MemoryStream을 파일 스트림에 쓰기

그런 다음 객체 역 직렬화를 위해 역순으로 수행하십시오.

+0

나는 배열이 컨테이너라는 인상 아래에 있었다. 처음에는 데이터 파일을 만든 다음 deserialize 할 때 제대로 작동합니다. 그리고 두 경우 모두 정확히 같은 DeserializeData 메서드를 호출합니다. – topofsteel

+0

@topofsteel - 아니요, ViewerData 객체와 정수가 아닌 배열을 직렬화합니다. 답을 게시 해 주셔서 감사합니다. BinaryFormatter가 이와 같이 작동한다는 것을 알면 흥미 롭습니다. 즉, deserialising은 스트림의 다음 객체 (int, ViewerData)에만 영향을 미칩니다. 그러나 이것은 내가 문서화되지 않은 행동으로 나는 그것에 따라 추천하지 않습니다. – groverboy

+0

이 문서화되지 않은 동작에 대한 자세한 내용은 [동시에 두 개 이상의 객체를 비 직렬화하려고합니다.] (http://stackoverflow.com/questions/13787723/trying-to-deserialize-more-than-1-object-at-the -same-time/13790222 # 13790222) 및 [특정 개체 비 순차 화] (http://stackoverflow.com/a/18383530/1015802). – groverboy

0

DeserializeData에서 viewerData를 다시 초기화해야합니다 (binPath 문자열). 그것이 UpdateDirectory()에서오고 있었다면 그것은 이미있었습니다.

viewerData = new ViewerData[length]; 

여러분 모두에게 감사드립니다.