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