BinaryFormatter序列化大容量数据, 会产生System.OutOfMemoryException异常

homeway78 2009-05-08 02:03:13
以下为示例代码, 当输入15000时或者以上会产生System.OutOfMemoryException异常,

另外同样的数据源, 使用DataTable和Object执行序列化, 得到的流长度差了两倍.

如何才能突破BinaryFormatter的容量, 另外DataTable和Object序列化后的不同如何解决.


protected void Serialize(int rowCount)

{

Console.WriteLine("时间:{0:yyyy-MM-dd HH:mm:ss ddd}, 序列化数据, 共{1}行.", DateTime.Now, rowCount);

//创建数据源

DataTable dt = new DataTable();

for (int index = 0; index < 100; index++)

{

dt.Columns.Add(string.Format("Col{0}", index), typeof(string));

}

for (int j = 0; j < 2e4; j++)

{

DataRow newRow = dt.NewRow();

for (int index = 0; index < 100; index++)

{

newRow[string.Format("Col{0}", index)] = string.Format("数值({0}) 加 数字({1}) 等于 值({2})", index, j, index + j);

}

dt.Rows.Add(newRow);

}

Console.WriteLine("时间:{0:yyyy-MM-dd HH:mm:ss ddd}, 已建立数据源.", DateTime.Now);

//序列化

MemoryStream stream = new MemoryStream();

new BinaryFormatter().Serialize(stream, dt);

Console.WriteLine("时间:{0:yyyy-MM-dd HH:mm:ss ddd}, 流长度{1:#,###}, 类型DataTable.", DateTime.Now, stream.Length);

//序列化

object obj = dt as object;

new BinaryFormatter().Serialize(stream, obj);

Console.WriteLine("时间:{0:yyyy-MM-dd HH:mm:ss ddd}, 流长度{1:#,###}, 类型Object.", DateTime.Now, stream.Length);

}
...全文
874 5 打赏 收藏 转发到动态 举报
写回复
用AI写文章
5 条回复
切换为时间正序
请发表友善的回复…
发表回复
zgke 2009-05-09
  • 打赏
  • 举报
回复
BinaryFormatter.Serialize(Stream,obj);
写入后是写到当前Stream的后面.不是重新生成一个Stream.
homeway78 2009-05-09
  • 打赏
  • 举报
回复
确实同一个对象被序列化了两次, 是个Bug.
那么BinaryFormatter是否有分布序列化的方式呢, 比如每次只写入固定长度的字节到流中, 然后转存出去.
wuyq11 2009-05-08
  • 打赏
  • 举报
回复
LS正确,序列化了两次

参考
参考
真相重于对错 2009-05-08
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 lextm 的回复:]
为了保证但序列化时能够有足够的类型信息,在你在序列化的时候,类型信息也是写入到序列化流内部的。由于DataTable和object的类型信息肯定不一样多,所以会造成序列化结果不一样。或者假设序列化结果完全一样,那么反序列化的结果难道会两样?那时候你又怎么区分是DataTable还是object呢?

至于OOM,要看到底是哪里溢出了。一般来说改用64位的操作系统可以减少OOM的情况,另外就是尽可能不要序列化那么大的对象了。
[/Quote]
瞎说,楼主 的代码错误
MemoryStream stream = new MemoryStream();

new BinaryFormatter().Serialize(stream, dt);

Console.WriteLine("时间:{0:yyyy-MM-dd HH:mm:ss ddd}, 流长度{1:#,###}, 类型DataTable.", DateTime.Now, stream.Length);

//序列化

object obj = dt as object;

new BinaryFormatter().Serialize(stream, obj);
同一个stream序列化同一个对象最后流大小当然是第一次序列化的一倍
lextm 2009-05-08
  • 打赏
  • 举报
回复
为了保证但序列化时能够有足够的类型信息,在你在序列化的时候,类型信息也是写入到序列化流内部的。由于DataTable和object的类型信息肯定不一样多,所以会造成序列化结果不一样。或者假设序列化结果完全一样,那么反序列化的结果难道会两样?那时候你又怎么区分是DataTable还是object呢?

至于OOM,要看到底是哪里溢出了。一般来说改用64位的操作系统可以减少OOM的情况,另外就是尽可能不要序列化那么大的对象了。

110,536

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧