C#从.dat文件反序列化列表并显示到文本框的问题
问题分析与解决方案
问题根源
你当前的读取问题源于写入逻辑:每次保存时都创建一个仅含单条数据的List<InPerson>,然后将整个List序列化后追加到文件中。这导致.dat文件里存储了多个独立的序列化List<InPerson>对象块,而非一个包含所有数据的完整List。而你读取时仅调用了一次Deserialize,自然只能拿到文件中的第一个List,后续的多个List对象完全没被处理。
另外必须注意:InPerson类必须标记[Serializable]特性,否则BinaryFormatter无法完成序列化/反序列化操作(你的代码中未体现这一点,这是必要前提)。
解决方案1:适配原有写入逻辑的读取代码
读取时循环调用Deserialize,直到文件流到达末尾(此时会抛出EndOfStreamException,捕获该异常即可终止循环):
第一步:给InPerson类添加序列化特性
[Serializable] public class InPerson { public int iId; public string sDate; public string sTime; public string sDuration; public string sPatientname; public string sPhonenumber; public string sDoctorid; public string sRoomnumber; public string sNurseid; // 你的构造函数保持不变 public InPerson(int iId, string sDate, string sTime, string sDuration, string sPatientname, string sPhonenumber, string sDoctorid, string sRoomnumber, string sNurseid) { this.iId = iId; this.sDate = sDate; this.sTime = sTime; this.sDuration = sDuration; this.sPatientname = sPatientname; this.sPhonenumber = sPhonenumber; this.sDoctorid = sDoctorid; this.sRoomnumber = sRoomnumber; this.sNurseid = sNurseid; } // 你的ToString方法保持不变 public override string ToString() { return "In Person Apppointment: " + iId + System.Environment.NewLine + "Date: " + sDate + System.Environment.NewLine + "Time: " + sTime + System.Environment.NewLine + "Duration: " + sDuration + System.Environment.NewLine + "Patients Name: " + sPatientname + System.Environment.NewLine + "Patients Number: " + sPhonenumber + System.Environment.NewLine + "Doctors ID: " + sDoctorid + System.Environment.NewLine + "Room Number: " + sRoomnumber + System.Environment.NewLine + "Nurse id: " + sNurseid + System.Environment.NewLine; } }
第二步:修正读取代码
const string filename = "appointments.dat"; BinaryFormatter bFormatter = new BinaryFormatter(); txtBookings.Text = ""; // 先清空文本框 using (FileStream inFile = new FileStream(filename, FileMode.Open, FileAccess.Read)) { try { while (true) { // 读取文件中的下一个List<InPerson>对象 List<InPerson> currentList = (List<InPerson>)bFormatter.Deserialize(inFile); // 遍历当前List的所有元素并追加到文本框 foreach (InPerson a in currentList) { txtBookings.Text += a.ToString() + "------------------------" + System.Environment.NewLine; } } } catch (EndOfStreamException) { // 文件读取完毕,终止循环 } }
解决方案2:优化写入逻辑(更合理的方式)
每次写入时先读取文件中已有的所有数据,合并成一个完整的List后再整体序列化覆盖文件,这样读取时只需一次反序列化即可获取所有数据:
优化后的写入代码
const string filename = "appointments.dat"; List<InPerson> allInPersonList = new List<InPerson>(); // 读取已有的预约数据(如果文件存在) if (File.Exists(filename)) { using (FileStream inFile = new FileStream(filename, FileMode.Open, FileAccess.Read)) { BinaryFormatter bFormatterRead = new BinaryFormatter(); try { while (true) { var existingList = (List<InPerson>)bFormatterRead.Deserialize(inFile); allInPersonList.AddRange(existingList); } } catch (EndOfStreamException) { // 读取完成 } } } // 添加新的预约 InPerson newInPersonApp = new InPerson( Convert.ToInt32(txtID.Text), dateTimePickerBooking.Text, txtTime.Text, txtDuration.Text, txtPatientName.Text, txtPhoneNumber.Text, txtDoctorID.Text, txtRoomAllocated.Text, txtNurseID.Text ); allInPersonList.Add(newInPersonApp); // 覆盖写入完整的List using (FileStream outFile = new FileStream(filename, FileMode.Create, FileAccess.Write)) { BinaryFormatter bFormatterWrite = new BinaryFormatter(); bFormatterWrite.Serialize(outFile, allInPersonList); }
对应简化的读取代码
const string filename = "appointments.dat"; txtBookings.Text = ""; if (File.Exists(filename)) { using (FileStream inFile = new FileStream(filename, FileMode.Open, FileAccess.Read)) { BinaryFormatter bFormatter = new BinaryFormatter(); List<InPerson> allList = (List<InPerson>)bFormatter.Deserialize(inFile); foreach (InPerson a in allList) { txtBookings.Text += a.ToString() + "------------------------" + System.Environment.NewLine; } } }
内容的提问来源于stack exchange,提问作者Alex
相关产品推荐
相关产品推荐

