序列化和反序列化的问题 内存中有一个DataTable,假设里面有100条数据我通过序列化存盘,然后清空DataTable,这时再往DataTable中插入100条数据,然后再序列化存盘,追加到文件末尾假设这样反反复复插了N条数据但是反序列化的时候只获得了前100条???(我在做聊天程序的聊天记录,或者谁有更好的方法,谢谢...) 解决方案 » 免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货 private void 序列化_Click(object sender, EventArgs e) { DataTable dt = new DataTable(); dt.Columns.Add("aaa"); dt.Columns.Add("bbb"); dt.Columns.Add("ccc"); for (int i = 0; i < 100; i++) { DataRow dr = dt.NewRow(); dr["aaa"] = i.ToString(); dr["bbb"] = DateTime.Now.ToString(); dr["ccc"] = Guid.NewGuid().ToString(); dt.Rows.Add(dr); } BinaryFormatter bf = new BinaryFormatter(); FileStream fs = new FileStream("info.dat", FileMode.Append,FileAccess.Write); bf.Serialize(fs, dt); fs.Close(); } private void 反序列_Click(object sender, EventArgs e) { FileStream fs = new FileStream("info.dat", FileMode.Open, FileAccess.Read); BinaryFormatter bf = new BinaryFormatter(); DataTable dt = (DataTable)bf.Deserialize(fs); this.dataGridView1.DataSource = dt; }代码还不都一样 FileStream fs = new FileStream("info.dat", FileMode.Append,FileAccess.Write);你这样每次都是相当于新建一个info.dat,会把原来的覆盖掉的 楼主如果是希望后加的记录能和以前的记录叠加,那么每次添加记录前必须从文件反序列化出DataTable对象,在这个对象中插入记录后再序列化。虽然以后的对象的确添加到了文件,但反序列化时只会从文件头开始尝试反序列化,还原出第一次的DataTable后,反序列化就完成了,尽管后面有新的序列化对象,但与前一个DataTable无任何联系。private void button1_Click(object sender, EventArgs e) { DataTable dt= Deserialize(); if (dt == null) { dt = new DataTable(); dt.Columns.Add("aaa"); dt.Columns.Add("bbb"); dt.Columns.Add("ccc"); } for (int i = 0; i < 2; i++) { DataRow dr = dt.NewRow(); dr["aaa"] = i.ToString(); dr["bbb"] = DateTime.Now.ToString(); dr["ccc"] = Guid.NewGuid().ToString(); dt.Rows.Add(dr); } BinaryFormatter bf = new BinaryFormatter(); FileStream fs = new FileStream("info.dat", FileMode.OpenOrCreate, FileAccess.Write); bf.Serialize(fs, dt); fs.Close();}private void button2_Click(object sender, EventArgs e){ Deserialize();} DataTable Deserialize() { string file = "info.dat"; if (File.Exists(file)) { try { FileStream fs = new FileStream(file, FileMode.Open, FileAccess.Read); BinaryFormatter bf = new BinaryFormatter(); DataTable dt = (DataTable)bf.Deserialize(fs); fs.Close(); this.dataGridView1.DataSource = dt; return dt; } catch{} } return null; } 我明白,有什么方法让一个DataRow对象添加到序列化过后的DataTable对象中呢?不然每次重新都读取,插入,序列化;N条数据的话吃不消的XML是个好方法 楼主是希望将这个文件当数据库用吗?那还是直接用数据库的好。不管是XML还是二进制的序列化,其一次能处理的数据量都有限,因为内存的限制,假设内存2G,不可能一次反序列化超过2G的数据。按你原来的思路,每次存储少量数据,其实也可以从文件按需取单个DataTable。但需要有一另一个文件存储标识,该文件主要是记录数据文件从何处开始反序列化。[Serializable] public class RecordFlag { private string tableName; /// <summary> /// 表名 /// </summary> public string TableName { get { return tableName; } set { tableName = value; } } private long dataLen; /// <summary> /// 本次DataTable序列化后的数据长度 /// </summary> public long DataLen { get { return dataLen; } set { dataLen = value; } } }比如我们定义一个如上的可序列化类,每次序列化前都从标识文件读出头,也就是List<RecordFlag>,在存DataTable时,在这个集合中添加一个RecordFlag对象,接下来是在数据文件Append表对象,获取文件增加的长度,更新RecordFlag的属性,重写标识文件,也就是重新序列化List<RecordFlag>到文件。这个过程稍有点麻烦,如果觉得这样不可取,还是用数据库吧。 这种方法,没办法读到所有的数据的。你应该在前面加头.比如先序列化到一个文件。得到这个文件的大小,然再再创建一个文件。把这个大小和位置记录到头。下次再重复弄。如果一次弄所有的。在序列化这个TABLE前。先把之前序列化的加进来。(我在做聊天程序的聊天记录,或者谁有更好的方法,谢谢...)?/这个你应该考虑顺序文件读写。 保存个小型本地库吧类似firebird 楼主还在踌躇中...存大量记录用数据库很省事的。如果文件几个G,查询数据的话,你的XML查记录觉得方便吗?XML文件要是只想加载部分数据似乎不那么方便吧。 一个驴肉火烧,再一个驴肉火烧,你连着吃了两个,能跟店家争辩说你只吃了一个驴肉火烧吗?编程应该稍微深入看看自己编写出来的东西。你写一个xml到文件,再写另一个xml追加到文件后边,能说这两个xml就是一个xml吗?道理何在? 我明白,N次追加文件之后里面就有N个DataTable对象,若想读取第二个则必须从DataTable1.length+1开始读.我想知道有没有什么方法可以将DataRow对象插入到序列化的表中呢 C# 并口(LPT) 获取开关量 怎么获取?在线等 winform 从上到下 从右到左 显示文字 dataGridView编辑问题 求:基于C#的上位机监控程序设计 c#下,数据库连接失败后在连接 网络流以及电子邮件的解析? 如果在一个类中使用FORM1.CS中的控件 gridview 如何固定行高? 使用BindingSource来新增行,然后Ds.AcceptChanges()时总是滚动到第一行 VS打开C#程序,如何添加图片所在的文件夹的路径 C# 截取文本框中选中的部分 关于Winform设计器问题
private void 序列化_Click(object sender, EventArgs e)
{
DataTable dt = new DataTable();
dt.Columns.Add("aaa");
dt.Columns.Add("bbb");
dt.Columns.Add("ccc");
for (int i = 0; i < 100; i++)
{
DataRow dr = dt.NewRow();
dr["aaa"] = i.ToString();
dr["bbb"] = DateTime.Now.ToString();
dr["ccc"] = Guid.NewGuid().ToString();
dt.Rows.Add(dr);
} BinaryFormatter bf = new BinaryFormatter();
FileStream fs = new FileStream("info.dat", FileMode.Append,FileAccess.Write);
bf.Serialize(fs, dt);
fs.Close(); } private void 反序列_Click(object sender, EventArgs e)
{
FileStream fs = new FileStream("info.dat", FileMode.Open, FileAccess.Read);
BinaryFormatter bf = new BinaryFormatter();
DataTable dt = (DataTable)bf.Deserialize(fs);
this.dataGridView1.DataSource = dt;
}代码还不都一样
你这样每次都是相当于新建一个info.dat,会把原来的覆盖掉的
虽然以后的对象的确添加到了文件,但反序列化时只会从文件头开始尝试反序列化,还原出第一次的DataTable后,反序列化就完成了,尽管后面有新的序列化对象,但与前一个DataTable无任何联系。
private void button1_Click(object sender, EventArgs e)
{
DataTable dt= Deserialize();
if (dt == null)
{
dt = new DataTable();
dt.Columns.Add("aaa");
dt.Columns.Add("bbb");
dt.Columns.Add("ccc");
}
for (int i = 0; i < 2; i++)
{
DataRow dr = dt.NewRow();
dr["aaa"] = i.ToString();
dr["bbb"] = DateTime.Now.ToString();
dr["ccc"] = Guid.NewGuid().ToString();
dt.Rows.Add(dr);
} BinaryFormatter bf = new BinaryFormatter();
FileStream fs = new FileStream("info.dat", FileMode.OpenOrCreate, FileAccess.Write);
bf.Serialize(fs, dt);
fs.Close();
}
private void button2_Click(object sender, EventArgs e)
{
Deserialize();
} DataTable Deserialize()
{
string file = "info.dat";
if (File.Exists(file))
{
try
{
FileStream fs = new FileStream(file, FileMode.Open, FileAccess.Read);
BinaryFormatter bf = new BinaryFormatter();
DataTable dt = (DataTable)bf.Deserialize(fs);
fs.Close();
this.dataGridView1.DataSource = dt;
return dt;
}
catch{}
}
return null;
}
不然每次重新都读取,插入,序列化;N条数据的话吃不消的
XML是个好方法
不管是XML还是二进制的序列化,其一次能处理的数据量都有限,因为内存的限制,假设内存2G,不可能一次反序列化超过2G的数据。按你原来的思路,每次存储少量数据,其实也可以从文件按需取单个DataTable。但需要有一另一个文件存储标识,该文件主要是记录数据文件从何处开始反序列化。
[Serializable]
public class RecordFlag
{
private string tableName;
/// <summary>
/// 表名
/// </summary>
public string TableName
{
get { return tableName; }
set { tableName = value; }
} private long dataLen;
/// <summary>
/// 本次DataTable序列化后的数据长度
/// </summary>
public long DataLen
{
get { return dataLen; }
set { dataLen = value; }
} }
比如我们定义一个如上的可序列化类,每次序列化前都从标识文件读出头,也就是List<RecordFlag>,在存DataTable时,在这个集合中添加一个RecordFlag对象,接下来是在数据文件Append表对象,获取文件增加的长度,更新RecordFlag的属性,重写标识文件,也就是重新序列化List<RecordFlag>到文件。
这个过程稍有点麻烦,如果觉得这样不可取,还是用数据库吧。
你应该在前面加头.比如先序列化到一个文件。得到这个文件的大小,然再再创建一个文件。把这个大小和位置记录到头。下次再重复弄。如果一次弄所有的。在序列化这个TABLE前。先把之前序列化的加进来。(我在做聊天程序的聊天记录,或者谁有更好的方法,谢谢...)?/这个你应该考虑顺序文件读写。
类似firebird
存大量记录用数据库很省事的。
如果文件几个G,查询数据的话,你的XML查记录觉得方便吗?
XML文件要是只想加载部分数据似乎不那么方便吧。
我想知道有没有什么方法可以将DataRow对象插入到序列化的表中呢