添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接
 1             //序列化
 2             string result = string.Empty;            
 3             using (MemoryStream stream = new MemoryStream())
 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);
10                 result = Convert.ToBase64String(objectBytes,Base64FormattingOptions.None);
12             }
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);

部分代码如上,在执行到上面的代码第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 是有反回值的,返回值表示实际读取了多少字节的数据,由于你写的代码本身逻辑不严谨,所以导致你无法很快发现错误,如果你一开始写代码时就考虑到返回值为 0 ,或者小于你需要读取的字节数的情况的话,虽然你的代码量会增加几行,但是却能避免错误的发生。

Launcher 园豆:45050 (高人七级) 2015-07-23 10:02