Binary stream '0' does not contain a valid BinaryHeader error on deserialization
Asked Answered
B

1

6

After searching for an answer to this issue for the last 2 days, I'm hoping someone here can help.

I have written a program in c# using VS2012 that saves the user's project data using BinaryFormatter to serialize a serializable class to a Stream before saving it to a file. The programme has been in use for some time, however recently a user couldn't open a file he saved the day before. He sent me the file, and the error I get in the degugger is:

"Binary stream '0' does not contain a valid BinaryHeader. Possible causes are invalid stream or object version change between serialization and deserialization."

Given the user saved the data the day before, there was no change to the underlying object structure or format between serialization and deserialization.

This problem has not come up before, leading me to believe it must be very intermittent, and therefore there is no obvious problem with the objects being serialized and deserialized.

The questions I have are:

My understanding of this error is that the format of the serialized data does not match the format of the object being deserialized into. Is this correct? Are there any other causes?

If so, what could cause this to be such an intermittent error?

Is there any way to retrieve the data from this file, even though the BinaryFormatter doesn't think it's in the correct format?

Is there a safer way to save and load data? I've seen that XmlFormatter seems to be a better choice, but how will this help with ensuring the integrity of the data being saved and recalled?

If it helps, the code I am using to serialize/ deserialize is as follows:

//serialize

SEProjectData serializedProject = serializeProjectData();

Stream stream = File.Open(saveFileDialog1.FileName, FileMode.Create);
BinaryFormatter bFormatter = new BinaryFormatter();
bFormatter.Serialize(stream, serializedProject);
stream.Close();

//deserialize

Stream stream = File.Open(path, FileMode.Open);
BinaryFormatter bFormatter = new BinaryFormatter();

stream.Seek(0, SeekOrigin.Begin);

SEProjectData projectData = (SEProjectData)bFormatter.Deserialize(stream);
stream.Close();
Bonny answered 9/4, 2013 at 16:54 Comment(0)
K
3

Yes, BinaryFormatter can be version intolerant (especially if you change the fields), but that usually raises a different error. The code you show is more or less fine (I'd use "using" to ensure prompt closure in exception). Without a repro it is hard to comment - I'm thinking "damaged file". Do you have the file? Is it perhaps zero-length? Was it ever transferred or stored other than on a file system? There are any number of ways to mess up file contents (see http://marcgravell.blogspot.com/2013/02/how-many-ways-can-you-mess-up-io.html).

If you want to solve the versioning issue, I'm partial to protobuf-net, but I'm very biased. It works exceptionally well for us though. But this doesn't sound quite like the usual versioning problem.

Kentiggerma answered 9/4, 2013 at 17:4 Comment(2)
Thanks for the response Mark. I do have the file, and it has a decent size. I looked at the contents in a text editor, and could make out the class names at the top of the text, so I believe it was generated by my programme, and like you my thoughts were that it may have been damaged during either serialization or storage. Out of interest, what do you mean by 'without a repro'?Bonny
You were correct Marc, it was a damaged file. I looked at the stream read position when the exception was thrown, checked that part of the file, and there's a huge region where the file consists of just 00 which is clearly not right. It's a worry that the file has either been damaged during serialization or after being saved. The only thing I could think of doing was immediately reloading and deserializing the file after saving to check its integrity, and then alerting the user if the file won't deserialize correctly. Thanks again for the help.Bonny

© 2022 - 2024 — McMap. All rights reserved.