Binary stream does not contain a valid BinaryHeader

B

BH

I'm trying a simple object serialization and deserialization, and keep
getting this error:

System.Runtime.Serialization.SerializationException: Binary stream does not
contain a valid BinaryHeader, 0 possible causes, invalid stream or object
version change between serialization and deserialization.

Here's my code. it does nothing but to serialize a DataTable object into a
byte array, and then read the byte array back for deserialization. I
verified that the byte array length did not change. the error occurs on the
object newObj = formatter.Deserialize(ms2); line.

public class Test {
Public Test {

DataTable dt = this.CreateDataSource();
System.IO.Stream ms= new System.IO.MemoryStream();
IFormatter formatter = new BinaryFormatter();
formatter.Serialize(ms, dt);

int numBytesToRead = (int) ms.Length;
byte[] bytes = new byte[numBytesToRead];
int numBytesRead = 0;
int n = ms.Read(bytes, numBytesRead, numBytesToRead);
ms.Position = 0;
ms.Close();

System.IO.Stream ms2= new System.IO.MemoryStream();
int numBytesToWrite = bytes.Length;
ms2.SetLength(numBytesToWrite);
int numBytesWritten = 0;
ms2.Write(bytes, numBytesWritten, numBytesToWrite);

ms2.Position = 0;
object newObj = formatter.Deserialize(ms2);

ms2.Close();
}


private DataTable CreateDataSource() {
DataTable dt = new DataTable();
DataRow dr;

dt.Columns.Add(new DataColumn("IntegerValue", typeof(Int32)));
dt.Columns.Add(new DataColumn("StringValue", typeof(string)));
dt.Columns.Add(new DataColumn("CurrencyValue", typeof(double)));

for (int i = 0; i < 10; i++) {
dr = dt.NewRow();

dr[0] = i;
dr[1] = "Item " + i.ToString();
dr[2] = 1.23 * (i+1);

dt.Rows.Add(dr);
}
return dt;
}
}
 
J

Jon Skeet

BH said:
I'm trying a simple object serialization and deserialization, and keep
getting this error:

System.Runtime.Serialization.SerializationException: Binary stream does not
contain a valid BinaryHeader, 0 possible causes, invalid stream or object
version change between serialization and deserialization.

Here's my code.

That's not your code. When you're going to post code, *please* post the
actual code - the code you posted doesn't compile. However, when
(adding using statements, etc) I got your code to compile, the problem
is pretty simple - and it's nothing to do with serialization, really.
public class Test {
Public Test {

DataTable dt = this.CreateDataSource();
System.IO.Stream ms= new System.IO.MemoryStream();
IFormatter formatter = new BinaryFormatter();
formatter.Serialize(ms, dt);

int numBytesToRead = (int) ms.Length;
byte[] bytes = new byte[numBytesToRead];
int numBytesRead = 0;
int n = ms.Read(bytes, numBytesRead, numBytesToRead);
ms.Position = 0;
ms.Close();

All the mistakes are in this section.

Firstly, you're trying to read *before* rewinding the stream - in other
words, you write to the stream, but then try to read *from the end*.

Secondly, when you read you're trying to read, you're trying to read at
the end of the byte array rather than the start.

Thirdly, you're assuming that everything will be read in one chunk
(which it probably will with a MemoryStream, but don't make that
assumption for streams in general). See
http://www.yoda.arachsys.com/csharp/readbinary.html for more details.

Fourthly, you're not flushing the stream after writing to it. Close()
will do this for you, and in a MemoryStream it's probably not necessary
anyway, but if you're going to do anything other than write then close,
I'd recommend calling flush anyway.

Now, taking the above points into consideration (except number 3 for
the moment, because it wasn't harming your code in reality, would be a
minor pain to demonstrate, is unnecessary for reasons explained in a
moment, and probably wouldn't be what you'd use in real serialization)
we end up with:

DataTable dt = CreateDataSource();
System.IO.Stream ms= new System.IO.MemoryStream();
IFormatter formatter = new BinaryFormatter();
formatter.Serialize(ms, dt);
ms.Flush();
ms.Position = 0;

int numBytesToRead = (int) ms.Length;
byte[] bytes = new byte[numBytesToRead];
ms.Read(bytes, 0, numBytesToRead);
ms.Close();

which works.

However, simpler is:
DataTable dt = CreateDataSource();
System.IO.Stream ms= new System.IO.MemoryStream();
IFormatter formatter = new BinaryFormatter();
formatter.Serialize(ms, dt);
ms.Flush();
byte[] bytes = ms.ToArray();
ms.Close();

Of course, simpler than that is just to rewind the memory stream and
use the same stream for deserializing as we just serialized into:

DataTable dt = CreateDataSource();
System.IO.Stream ms= new System.IO.MemoryStream();
IFormatter formatter = new BinaryFormatter();
formatter.Serialize(ms, dt);
ms.Flush();
ms.Position=0;
object newObj = formatter.Deserialize(ms);
ms.Close();

but maybe that doesn't show what you wanted to show.

Anyway, hope this helped.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,483
Members
44,901
Latest member
Noble71S45

Latest Threads

Top