1 //序列化 2 string result = string.Empty; 3 using (MemoryStream stream = new MemoryStream()) 4 { 5 BinaryFormatter formatter = new BinaryFormatter(); 6 formatter.Serialize(stream, payslip); 7 byte[] objectBytes = new byte[stream.Length]; 8 stream.Read(objectBytes, 0, (int)stream.Length); 9 10 result = Convert.ToBase64String(objectBytes,Base64FormattingOptions.None); 11 12 } 13 14 15 //反序列化 16 byte[] array = Convert.FromBase64String(result); 17 using (MemoryStream stream = new MemoryStream(array)) 18 { 19 BinaryFormatter de = new BinaryFormatter(); 20 object obj = de.Deserialize(stream); 21 }
部分代码如上,在执行到上面的代码第20行,反序列化时报错如下:
二进制流“0”不包含有效的 BinaryHeader。这可能是由于无效流,或由于在序列化和反序列化之间的对象版本更改
上面的测试代码为了排除其他原因,都写在一个方法体内,序列化后立马反序列化:
1,先将payslip对象序列化为字节组。
2,再将字节组反序列化为对象。
直接报错, 后来在搜索了一下答案,说可以加个Base64转换操作,加了之后还是报一样的错!
特此向大家求教!
为什么加个 Base64 转换操作就正确了?你应该没想过这个问题吧!
而事实是你对 Stream 的使用错误。
formatter.Serialize(stream, payslip);
执行此语句后,stream 的当前读写位置已经移动到流的尾部了,所以你再执行 stream.Read 的时候,它是从流的尾部开始读取,而你想要的是从流的开始位置读取。
因此,正确的代码应该是这样:
formatter.Serialize(stream, payslip);
stream.SeekToBegin();
stream.Read(objectBytes, 0, (int)stream.Length);
然后你就可以使用 objectBytes 来构建新的 MemoryStream,并反序列化。
事实上,如果你在出现错误后,能够一步一步的跟踪下变量的值,你也应该发现问题,比如在 stream.Read(objectBytes, 0, (int)stream.Length) 语句调用后,你观察下 objectBytes 中的值。
谢谢你,确实是Stream读取位置造成的。我在Read之前重新设置了Postion就好了
stream.Position = 0;
还是对Stream理解不深。事实上我调试时确实发现objectBytes中都是0,但是不知道是什么原因造成的。
十分感谢!
@庸俗: 另外 Stream.Read 是有反回值的,返回值表示实际读取了多少字节的数据,由于你写的代码本身逻辑不严谨,所以导致你无法很快发现错误,如果你一开始写代码时就考虑到返回值为 0 ,或者小于你需要读取的字节数的情况的话,虽然你的代码量会增加几行,但是却能避免错误的发生。
@Launcher: Stream.Read 的返回值这个了解,如果当时检查下应该是可以发现问题的。