4
votes

I'm creating a viewer. The first time you go to a directory, you create the data file by processing the files, exacting the images and Serializeing the data into a data file. I then Deserialize that newly created file into the form to be viewed. The second time you go to a directory, it sees that file ans tries to Deserialize it to populate the form. The system works fine when it has to create it first, but if it's already there I receive an unreferenced object error. What am I missing?

 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
        }

Edit:

Error: Object reference not set to an instance of an object - at line commented 'problem' in first for loop in DeserializeData(string binPath);

Stack trace...

at Substance_Browser_12.Form1.DeserializeData(String binPath) in X:\Visual Studio 2010\Projects\Substance Designer\Substance_Browser_12\Substance_Browser_12\Form1.cs:line 151 at Substance_Browser_12.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& m) at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m) at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m) at 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) at System.Windows.Forms.Control.SendMessage(Int32 msg, IntPtr wparam, IntPtr lparam) at System.Windows.Forms.Control.ReflectMessageInternal(IntPtr hWnd, Message& m) at System.Windows.Forms.Control.WmNotify(Message& m) at System.Windows.Forms.Control.WndProc(Message& m) at System.Windows.Forms.ScrollableControl.WndProc(Message& m) at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m) at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m) at System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam) at 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& m) at System.Windows.Forms.TreeView.WmMouseDown(Message& m, MouseButtons button, Int32 clicks) at System.Windows.Forms.TreeView.WndProc(Message& m) at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m) at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m) at System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, 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) at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly() at System.Threading.ThreadHelper.ThreadStart_Context(Object state) at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx) at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx) at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state) at System.Threading.ThreadHelper.ThreadStart()

4
On which line do you get the unreferenced object error?crthompson
can you provide error message and stack trace?Grundy
Thanks for adding the actual exception text. "Object reference not set to instance of an object" does not mean the same thing as "unreferenced object error", this is misleading.groverboy

4 Answers

0
votes

in msdn BinaryFormatter.Deserialize Method (Stream)

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

so possibly when you try deserialize current position in the stream does not at the beginning of the object graph.

0
votes

You are serialising multiple ViewerData objects to one file but there's no container for these objects in the file. I don't think BinaryFormatter supports this usage. Alternative ways of serialising these objects:

  • Serialise one ViewerData per file.
  • Add all ViewerData objects to a collection, then serialise the collection. You may get out of memory errors with this approach if there are many large images.
  • Develop an algorithm that combines BinaryFormatter with manual writes/reads, to avoid using excessive memory. This probably needs an intermediate stream, e.g. MemoryStream for serialising each ViewerData. See pseudo code steps below.

Write count of objects to file stream.
For each object. Serialise using BinaryFormatter to MemoryStream. Write length of MemoryStream to file stream. Write MemoryStream to file stream

Then do the reverse for deserialising the objects.

0
votes

I needed to reinitialize viewerData in DeserializeData(string binPath). If it was coming from UpdateDirectory() it already had been.

viewerData = new ViewerData[length];

Thanks everyone for your input!

0
votes

you only need to change to this

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