这是流写入的方法代码
private void btnSave_Click(object sender, EventArgs e)
{
string file = @"d:\student.dat";
Stream stream = new FileStream(file, FileMode.Append, FileAccess.Write);
BinaryFormatter bf = new BinaryFormatter();
bf.Serialize(stream, list);
stream.Close();
}
怎么就 用FileMode.Append无法添加内容呢,但换成 FileMode.OpenOrCreate就可以,用还有个问题出现就是
用FileMode.OpenOrCreate,每次重新输入内容,上次写的内容,就会消失(好像是被覆盖刷新了一样)
完整代码
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
namespace _8_4
{
public partial class frmDemo : Form
{
private StudnentList list=new StudnentList();
private int i = 0;
public frmDemo()
{
InitializeComponent();
}
#region 保存按钮
private void btnAdd_Click(object sender, EventArgs e)
{
Student student = new Student(textBox1.Text, textBox2.Text, textBox3.Text);
list[i] = student;
i++;
}
#endregion
#region 添加按钮
private void btnSave_Click(object sender, EventArgs e)
{
string file = @"d:\student.dat";
Stream stream = new FileStream(file, FileMode.Append, FileAccess.Write);
BinaryFormatter bf = new BinaryFormatter();
bf.Serialize(stream, list);
stream.Close();
}
#endregion
#region 显示按钮
private void btnShow_Click(object sender, EventArgs e)
{
string file = @"d:\student.dat";
Stream stream = new FileStream(file, FileMode.Open, FileAccess.Read);
BinaryFormatter bf = new BinaryFormatter();
StudnentList students = (StudnentList)bf.Deserialize(stream);
int k = 0;
while (students[k] != null)
{
string s_no = students[k].student_no;
string name = students[k].name;
string depart = students[k].department;
int a = students[k].a;
string result = string.Format("{0}\t{1}\t{2}", s_no, name, depart );
lbResult.Items.Add(result);
k++;
}
stream.Close();
}
#endregion
}
[Serializable]
public class Student
{
public int a = 3;
public string student_no;
public string name;
public string department;
public Student(string s_no, string name, string depart)
{
this.student_no = s_no;
this.name = name;
this.department = depart;
}
}
//studentlist类的
[Serializable]
public class StudnentList
{
private Student[] list = new Student[100];
public Student this[int index]
{
get
{
if (index < 0 || index >= 100)
{
return list[0];
}
else
{
return list[index];
}
}
set
{
if (!(index < 0 || index >= 100))
{
list[index] = value;
}
}
}
}
}
((上图是操作界面)
用FileMode.OpenOrCreate得到的第一次结果
第二次输入的内容
(FileMode.OpenOrCreate有时灵,有时不能运行)
希望,老师们指导,谢谢了,总结我的问题就是
问题1怎么就 用FileMode.Append无法添加内容呢,但换成 FileMode.OpenOrCreate就可以
问题2 用了还有个问题出现就是
用FileMode.OpenOrCreate,(关闭后再重新打开程序)每次重新输入内容,上次写的内容,就会消失(好像是被覆盖刷新了一样),我就不明白,我的代码不是说明,我就不明白,(假设一次我们输入10条内容,就可以保存10条,但这次输入新内容后,上次的10条内容就没了)啊,为什么??? 我上次建立的那个List(每重新运行程序StudnentList list=new StudnentList()就会生成一个新的StudnentLis类的listt对象)内容不是存入了d:\student.dat文件了吗(只不过每个LIst只能存100条学生记录,但List数量应该不限制啊)?照理来说应该是输出student.dat文件里的所有内容,呈现出以下效果啊
{10101 拍拍 接口3
1212 现在的内容 怎么刚才的10101那行没了
10101 拍拍 接口3
1212 现在的内容 怎么刚才的10101那行没了
........................应该是两行两行的重复出现才对啊
}
怎么我上次输入的内容都没了
是的,序列化數據,寫入是不能追加的。只能是一個整體。
那么请问我的2跟3问,老师怎么看
问题2 用了还有个问题出现就是
用FileMode.OpenOrCreate,每次重新输入内容,上次写的内容,就会消失(好像是被覆盖刷新了一样),照理来说应该是这样的
{10101 拍拍 接口3
1212 现在的内容 怎么刚才的10101那行没了
10101 拍拍 接口3
1212 现在的内容 怎么刚才的10101那行没了
........................应该是两行两行的重复出现才对啊
}
@黑夜猫头鹰: 我測試 沒有問題哦。只是代碼int k = 10;應該是int k = 0;
@無限遐想: 其實,是一個文件一個實體。因此 應該是複寫的哦。
@無限遐想: 其實串行化,主要是BinaryFormatter這個方法的問題。BinaryFormatter怎麼寫我們并不清楚。正常是這個方法只能複寫。
@無限遐想: 请问下,你是说你你新写入的内容不会覆盖原来的内容吗?
以这种规律呈现结果吗
{10101 拍拍 接口3
1212 现在的内容 怎么刚才的10101那行没了
10101 拍拍 接口3
1212 现在的内容 怎么刚才的10101那行没了
........................应该是两行两行的重复出现才对啊
}
麻烦了,请说仔细点,我比较笨,不是很懂你意思
@黑夜猫头鹰: 會覆蓋,不過,不會出現有時會顯示,有時會不顯示的問題。
@無限遐想: 我 不明白,我的代码不是说明,可与保存100学生的信息吗,这里却只能保存一个啊,为什么???
@黑夜猫头鹰: 是可以保存100個哦。你都放到Student里了。是100個哦。
@無限遐想: 不好意思,我的表达有点问题,我是说
应该可以有无数个List(每重新运行程序StudnentList list=new StudnentList()就会生成一个新的StudnentList类的list对象)才对啊(只要d:\student.dat中的student.dat文件足够大就行),只是每个List里面只能放100条数据而已,我理解的代码错误了吗?
可是每次重新输入内容,第一次输入的List内容就没了?这是为什么啊?
@黑夜猫头鹰: 是覆蓋了。因為你每次都寫入一個哦。只能讀取出來,然後再寫入。寫入一個數組。
@無限遐想:那我上次写的内容呢,我都没删除上次的内容,假设我们往一个txt文本,添加内容,但当我们下次打开时,我们上次写的内容一样能看到啊
我知道我每次只写一个,但是我每次写得的时候(每重新运行程序StudnentList list=new StudnentList()就会生成一个新的StudnentList类的list对象),假设我校有物理专业,化学专业,生物专业,我想把每个专业的前100名输出来,那我分3次录入d:\student.dat文件,当我读取 student.dat文件时,应该将我的3个list内容读取出来才对啊,为什么会覆盖呢?求解释,代码哪里导致覆盖了??那我要如何改写代码才可解决我的想法呢(假设我校有物理专业,化学专业,生物专业,我想把每个专业的前100名输出来),求详细解释
@黑夜猫头鹰: 你用讀出來的數據,初始化StudnentList,然後在StudnentList里再添加。然後寫入。
@無限遐想: 你回答太简短了,我都不明你说什么?(你用讀出來的數據,初始化StudnentList),我读来的数据都显示在listbox中,如何还能初始化。
@黑夜猫头鹰: StudnentList students = (StudnentList)bf.Deserialize(stream);這裡你已經初始化了這個對象。那麼再添加的時候對象的時候,就可以往這里添加了。把這句改成
list= (StudnentList)bf.Deserialize(stream);先調用這句,在做添加功能。
@無限遐想: 我用了你的方法,可是系统说不存在list变量,源代码对应位置是这样:
string file = @"d:\student.dat";
Stream stream = new FileStream(file, FileMode.Open, FileAccess.Read);
BinaryFormatter bf = new BinaryFormatter();
//原本是StudnentList students= (StudnentList)bf.Deserialize(stream);
list= (StudnentList)bf.Deserialize(stream);
int k = 0;
while (students[k] != null)
{
string s_no = students[k].student_no;
string name = students[k].name;
string depart = students[k].department;
string result = string.Format("{0}\t{1}\t{2}", s_no, name, depart);
lbResult.Items.Add(result);
k++;
}
把这句
StudnentList students = (StudnentList)bf.Deserialize(stream); 改成
list= (StudnentList)bf.Deserialize(stream); 报错了,是不是我弄错了?不好意思了?我那么多问题
@黑夜猫头鹰: private StudnentList list=new StudnentList();你不是有定義嗎?
怎麼會報錯呢?
除非 讀出來是空的。如果是空的,就不用初始化。
@無限遐想: 我不骗你的,真的是报错啊,我好想吧项目解决方案发给你啊,但我又不知怎么发才对,你能去我迅雷网盘哪里下载看看不http://dynamic.xlpan.com/file/192477228/66a3cf96-6c02-4e37-94ea-5b4d2463cd19
这是金山T盘网址http://d.1tpan.com/tp0216878644
@黑夜猫头鹰: 好。我測試一下。
@無限遐想: 我給你 改了一下。沒有問題了。其實,也能寫進去了。只不過你顯示的時候有問題。i變量給數值也有問題。導致 數據中間有null的數據。因此碰到null,就跳出了。不做處理。
下載地址:files.cnblogs.com/Teco/8-4.rar
@無限遐想:
问题1:我把list的数量有100改成了5(在 public class StudnentList的类定义中),做了个实验
private Student[] list = new Student[5];
public Student this[int index]
{
get
{
if (index < 0 || index >= 5)
{
return list[0];
}
else
{
return list[index];
}
}
set
{
if (!(index < 0 || index >= 5))
{
list[index] = value;
}
不知道为什么到list[4]就无法输出,程序卡死,好像一个 new Student[5],无法保存5个学生信息(数量>=5时,程序无法运行)?这又是为什么
问题2:好像无法解决我的问题(假设我校有物理专业,化学专业,生物专业,我想把每个专业的前100名输出来),你的那种方法好像所有学生都的必需保存在同一个StudnentList类对象中,变成了学生总和
(物理+化学+生物=100),那我就不能分类填写了。。。
其实我是想这样保存的
StudnentList 物理专业=new StudnentList();//保存物理前100学生
StudnentList 化学专业=new StudnentList()//保存化学前100学生
StudnentList 生物专业=new StudnentList()//保存生物前100学生
物理,化学,生物,是不同的StudnentList 实例
求分点解答
@黑夜猫头鹰: 我這裡 運行 沒有問題。可以一直添加哦。
@無限遐想: 大哥,求解答,感谢你了
问题:好像无法解决我的问题(假设我校有物理专业,化学专业,生物专业,我想把每个专业的前100名输出来),你的那种方法好像所有学生都的必需保存在同一个StudnentList类对象中,变成了学生总和
(物理+化学+生物=100),那我就不能分类填写了。。。
其实我是想这样保存的
StudnentList 物理专业=new StudnentList();//保存物理前100学生
StudnentList 化学专业=new StudnentList()//保存化学前100学生
StudnentList 生物专业=new StudnentList()//保存生物前100学生
物理,化学,生物,是不同的StudnentList 实例分组,每组有100个学生,
然后我用选择器,如选择只输出物理前100名学生,是使用者能有条件看他们所需的内容
@黑夜猫头鹰: 那 你 每一個 專業 保存一個文件。或則建立一個list<StudnentList >,寫入文件。一個都實現了。多幾個不是一樣嗎?
@無限遐想: 我自己这样弄是没问题,但是我做的这个系统是给别人用得,她不知道如何改代码的(string file = @"d:\student.dat").............她就不会更改保存路径.....,你能教教我实现我想要的功能吗?
其实我是想这样保存的
StudnentList 物理专业=new StudnentList();//保存物理前100学生
StudnentList 化学专业=new StudnentList()//保存化学前100学生
StudnentList 生物专业=new StudnentList()//保存生物前100学生
物理,化学,生物,是不同的StudnentList 实例分组,每组有100个学生,
然后我用选择器,如选择只输出物理前100名学生,便于使用者能有条件看他们所需的内容
@黑夜猫头鹰: 你可以把路徑寫到app.config中,這樣就可以改路徑了哦。
@無限遐想: 其实我想问个问题,你的原话(序列化數據,寫入是不能追加的。只能是一個整體。),你想告诉我,在同一文件中序列化对象的实例只能保存一个吗?若2个以上,就会出现我所遇到的问题,即是覆盖上一个对象,
所以我想将物理,化学,生物, 保存为3个StudnentList不同实例但又要在同一文件中,是不可能的吗?是么??只能保存在3个文件中,而不能保存在同一个d:\student.dat文件中
我的理解对吗?求哥哥指导?
哥哥
@黑夜猫头鹰: 嗯。是的。還有一個是你在student類中,再加一個屬相。來標示科目類別。這樣一個文件也可以。不過這樣的話,列表是300.明白了吧。
@無限遐想:大哥,我想再问个问题就是,我真的无法遍历索引器list
我把list的数量有100改成了5(在 public class StudnentList的类定义中),做了个实验
private Student[] list = new Student[5];
public Student this[int index]
{
get
{
if (index < 0 || index >= 5)
{
return list[0];
}
else
{
return list[index];
}
}
set
{
if (!(index < 0 || index >= 5))
{
list[index] = value;
}
遍历到list[4]时,就是无法输出,你能看下代码有什么错误吗?
地址 http://d.1tpan.com/tp1634496200
真的,本来不想再打扰你的,但我弄了两天了,还是无法解决?
当你输入5个学生信息,这真是不能输出,无法遍历list所有内容
@黑夜猫头鹰: 我找不到你的代碼。應該不會的。你要保存完,再點添加的哦,
@無限遐想: 我也是这样弄的,就是不行,希望你看看代码有没问题,我重发我的代码,麻烦了
http://dynamic.xlpan.com/file/192477228/f24d02de-df49-473b-897e-d29a37747caf
@黑夜猫头鹰:
[Serializable] public class StudnentList { private Student[] list = new Student[5]; public Student this[int index] { get { if (index < 0 || index >= 5) { return null; } else { return list[index]; } } set { if (!(index < 0 || index >= 5)) { list[index] = value; } } } }
代碼 改成null。不要返回 list[0]
@無限遐想: 为什么改为null就行啊,这跟返回list[0]有区别吗?我核对过关于索引器概念理论知识,我的这种遍历方法应该不存在什么问题哈?改为null跟我们遍历数组list[5]有关系吗?不明白其中其中的原理,我不甘心啊,我弄了几天了这道题。
恳求你指导一下我这菜鸟?告诉我是什么原因引发的错误?导致无法遍历数据呢?
谢谢了你了,麻烦你几天了,真的非常感谢你?
@黑夜猫头鹰: 返回 list[0]是死循環
@無限遐想: 怎么就死循环了,输出list[0],list1[],list[2],list[3]都没问题,到list[4]就死循环,怎么list[3]就不死循环呢?怎么回事啊?从代码来说当我们不满足条件时就会跳出循环啊,怎么就死了?
@黑夜猫头鹰: while (students[k] != null)
{
@無限遐想: 谢谢
谢谢,我明白了。
@無限遐想: 不好意思,大哥,还是要麻烦了,这个问题是承接上次那个问题,所以我觉得问你比较好,希望你能指点指点。
问题地址:http://q.cnblogs.com/q/36497/
打扰你了,大哥,真抱歉。希望你抽点时间看看我问题。不胜感激
没细看你的代码,感觉你中间有几个问题:
1——
你是要对数据进行追加,追加的数据是一个LIST,通过序列化为二进制流后追加。
这样的问题。。。很明显,假如追加成功的话,你这个文件里的数据将是多个LIST数据,你还能通过对这个文件进行反序列化后读取所有的数据吗?
2——
你用的这个方案我从来没用过,所以也无法指出错误所在。
我想,你之所以APPEND会失败,那可能是因为你用了数据序列化的原因。
或者你可以这样:
private void btnSave_Click(object sender, EventArgs e) { string file = @"d:\student.dat"; Stream stream = new FileStream(file, FileMode.Append, FileAccess.Write); BinaryFormatter bf = new BinaryFormatter(); MemoryStream ms = new MemoryStream(); bf.Serialize(ms, list); ms.Seek(0, SeekOrigin.Begin); stream.Write(ms.ToArray(), 0, ms.Length); stream.Close(); }
对于这一问(假如追加成功的话,你这个文件里的数据将是多个LIST数据,你还能通过对这个文件进行反序列化后读取所有的数据),我觉得系统会自动区分LISTS数据的,这个跟ReadString()一样,我输入很多不同的string数据,但还是可以读取来,不知我对原句理解真确否?还望指导
@黑夜猫头鹰: 因为我没这样做过,所以没办法确认,个人感觉是不可以的。
假如可以的话,你就用我的第二个方案试看。
@笨笨蜗牛: 我想问个问题是:我的代码不是说明,可与保存100学生的信息吗,这样就这能保存一个啊,为什么???如何保存100个学生记录? (其实就是问题2)
@黑夜猫头鹰: 只能保存一个,那你要检查你的LIST里的数据是否有100个。假如你的LIST里只有一个,当然只能保存一个了。
@笨笨蜗牛: 牛哥,我不懂你意思呢??
(private Student[] list = new Student[100])
应该可以有无数个List才对啊(每重新运行程序StudnentList list=new StudnentList()就会生成一个新的StudnentList对象)(只要d:\student.dat中的student.dat文件足够大就行),只是每个List里面只能放100条数据而已,我理解的代码错误了吗?
@黑夜猫头鹰: 似乎是这样,但具体的就很难说了,只能在你的代码里找问题了。从你目前提供的信息来说,还真的不知道该怎么去帮助你把问题解决。
另外,你可以调试下,在你执行存储的时候,list虽然的容量有100个,但其中是否只有一个元素是有对象的,而其它的99个都是为null呢?
@笨笨蜗牛: 牛哥,我还另外谢了一个方法去读取d:\student.dat文件的内容却读不了,但我查看d:\student.dat文件大小,确实每写入一次内容查看student.dat都变大了(从一开的几kb到现在的十几kb),不信你可以做做实验,我觉得数据内容还在的(我不相信原来的数据被删除或者是覆盖的想法),就是读取不出了而已,只能读出最后一次写入的内容?,希望牛哥,能写一个读取d:\student.dat文件所有内容的方法,验证我原来的数据内容是否还在?
@黑夜猫头鹰: 这就是我说的你把不同的对象序列化到同一个文件中,却没有自己组织数据结构,所以读取不了。
@笨笨蜗牛: 可以最后一次有可以的,这是什么情况呢?
@黑夜猫头鹰: 你可以做一个数据跟踪,每次写入数据后,分析下这个dat文件的内容。分析方法就是看下二进制文件(可以通过VS以二进制方式打开),在二进制文件中,你会看到一些很熟悉的内容的。
@笨笨蜗牛: 牛哥,不会写一个数据跟踪方法(VS以二进制方式打开),我试了很多,出了很多错误
@黑夜猫头鹰: 晕倒。你不是每次都把数据对象(LIST)写到了STUDENT.DAT文件了吗?每次写完后,你用VS去打开这个文件,打开的时候选择以二进制方式打开,这个时候你就可以在二进制状态查看这个文件了,此时你会看到一些你感兴趣的东西的。然后自己分析下,会发现一些问题。
@笨笨蜗牛: 牛哥,我的内容都是序列化的对象,好像不能这样读取的,二进制的方法写出来后,有好多错误弹出
一定要看这篇文章:C# 温故而知新:Stream篇(四)FileStream
我看了你给内容,可能我能力有限,我还是解决不了问题,你帮我解决下我的第二个问题吗?
问题2 用了还有个问题出现就是
用FileMode.OpenOrCreate,(关闭后再重新打开程序)每次重新输入内容,上次写的内容,就会消失(好像是被覆盖刷新了一样),我就不明白,我的代码不是说明,可与保存100学生的信息吗,这里只能保存一次的内容(假设一次我们输入10条内容,就可以保存10条,但这次输入新内容上次的10条内容就没了)啊,为什么??? 我上次建立的那个List内容不是存入了d:\student.dat文件了吗?照理来说应该是输出student.dat文件里的所有内容,呈现以下的输出这样效果啊
{10101 拍拍 接口3
1212 现在的内容 怎么刚才的10101那行没了
10101 拍拍 接口3
1212 现在的内容 怎么刚才的10101那行没了
........................应该是两行两行的重复出现才对啊
}
使用FileMode.Append前,确保该文件已经存在,试下:
Stream stream = new FileStream(file, File.Exists(file)?FileMode.Append:FileMode.OpenOrCreate, FileAccess.Write);