解析完成前遇到的流结束

本文关键字:结束 遇到 | 更新日期: 2023-09-27 18:05:29

我试图从一个文件中读取多个对象,下面的代码:

List<Alarm> list = new List<Alarm>();
BinaryFormatter serializer = new BinaryFormatter();
using (FileStream stream = File.OpenRead("//my File here"))
{
    while (stream.Position < stream.Length)
    {
        list.Add((Alarm)serializer.Deserialize(stream));
    }
}

然而,每次我试图运行这段代码,我得到一个错误,如"在解析完成之前遇到的流结束"。请注意,已经有一个线程建议在每次迭代后将流的位置设置为0,但这显然不适合我,否则我会陷入无限循环。

我在这里做错了什么?如果我省略while循环,代码本身就可以工作,但显然,在包含多个对象的文件中,我不想只从文件中获取一个对象,而是要从文件中获取所有对象。

任何建议吗?

编辑:随需应变:

序列化。

//Fetches Data from my GUI, creates a valid Alarm object
Alarm alarm = new Alarm(this.noticeBox.Text, date.Year, date.Month, date.Day, (int)this.hourPicker.Value, (int)this.minutePicker.Value);
var serializer = new BinaryFormatter();
using (FileStream stream = "//file"))
{
        serializer.Serialize(stream, alarm);
}

解析完成前遇到的流结束

如果您序列化的是Alarm s的列表(而不是一系列单独的Alarm s),这是很有可能的,那么您只需要反序列化它:

using (FileStream stream = File.OpenRead("//my File here"))
{
   list = (List<Alarm>)serializer.Deserialize(stream));
}

否则,如果你序列化独立的Alarm对象,你的代码应该工作(他们每个人都将是一个对象图本身,这似乎不是情况)

编辑:你张贴的一切似乎都很好。我在这里添加了一个小提琴(https://dotnetfiddle.net/bGWOOO),它演示了您使用的方法是如何工作的(出于明显的原因,我使用MemoryStream而不是FileStream,但这应该无关紧要)。所以还有其他问题:要么流没有正确地写入磁盘,要么没有正确地读取,但这与你发布的代码无关,绝对。

<标题> 更新

只是为了进一步参考为什么选择这个答案(因为真正的答案在评论/聊天中):

在序列化器中,您每次都创建文件并替换内容(未在问题中显示,但在注释中猜到了),因此答案正确地附加到文件中,如下所示:

using (FileStream stream = new FileStream("** path to file here**", FileMode.Append,  FileAccess.Write, FileShare.Write))
{
  // write the serialized data to the stream
}
This is a proof of how to serialize / deserialize an object using BinaryFormatter:
List<String> ls = new List<string>();
        ls.Add("aaa");
        ls.Add("Bb");
        BinaryFormatter bf = new BinaryFormatter ();
        var fileName = Guid.NewGuid ().ToString ().Replace ("-","");
        var path = Path.Combine (Environment.GetFolderPath (Environment.SpecialFolder.CommonApplicationData), fileName);
        try
        {
            using (var fs = new FileStream(path, FileMode.OpenOrCreate, FileAccess.Write))
            {
                bf.Serialize(fs, ls);
            }
            using (var fs = new FileStream(path, FileMode.Open, FileAccess.Read))
            {
                ls = bf.Deserialize(fs) as List<String>;
            }
        }
        finally
        {
            if (File.Exists (path))
            {
                try
                {
                    File.Delete(path);
                }
                catch
                {
                }
            }
        }

看起来您只需要在序列化之前将警报添加到警报列表中。这工作,似乎做你想要的:

void Main()
{
    List<Alarm> listYouSerializeInto = new List<Alarm>();
    listYouSerializeInto.Add(new Alarm("test", 2015, 07, 29, 06, 00));
    listYouSerializeInto.Add(new Alarm("test", 2015, 07, 29, 07, 00));
    listYouSerializeInto.Add(new Alarm("test", 2015, 07, 29, 08, 00));
    var serializer = new BinaryFormatter();
    using (FileStream stream = new FileStream(@"C:'Temp'alarm.bin", FileMode.Create))
    {
        serializer.Serialize(stream, listYouSerializeInto);
    }
    List<Alarm> listYouDeserializeInto = new List<Alarm>(); 
    using (Stream stream = new FileStream(@"C:'Temp'alarm.bin", FileMode.Open))
    {
        listYouDeserializeInto = (List<Alarm>)serializer.Deserialize(stream);
        foreach (Alarm a in listYouDeserializeInto)
        {
            Console.WriteLine(a);
        }

    }

}
// Define other methods and classes here
[Serializable]
public class Alarm {
    public string Text { get; set;}
    public int Year { get; set;}
    public int Month { get; set;}
    public int Day { get; set;}
    public int Hour { get; set;}
    public int Minute { get; set;}
    public Alarm (string text, int year, int month, int day, int hour, int minute)
    {
        Text = text;
        Year = year;
        Month = month;
        Day = day;
        Hour = hour;
        Minute = minute;
    }
}