【问题标题】:End of stream encountered before parsing was completed解析完成前遇到的流结束
【发布时间】:2015-07-29 18:07:15
【问题描述】:

我正在尝试使用以下代码从文件中读取多个对象:

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);
}

【问题讨论】:

  • 您能否提供一个简短但完整的程序来演示该问题,包括编写文件开头的代码?
  • 你有没有想过另一种方法看看这个帖子stackoverflow.com/questions/29284671/…
  • 有多少对象成功进入列表?应该有多少个对象?
  • 你是如何序列化列表的?作为一个洞列表?如果是这样,您只需将所有文件内容读入一个字节数组并调用一次反序列化。更不用说我建议在 FileStream 上使用 StreamReader
  • 警报类的代码在哪里?请提供它

标签: c#


【解决方案1】:

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

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

否则,如果您已经序列化了独立的 Alarm 对象,您的代码应该可以工作(每个对象本身都是一个对象图,但似乎并非如此)

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

更新

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

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

using (FileStream stream = new FileStream("** path to file here**", FileMode.Append,  FileAccess.Write, FileShare.Write))
{
  // write the serialized data to the stream
}

【讨论】:

  • 这是一个充满警报的文件,而不是警报列表。我可以把它做成那种方式,但我更喜欢用单个警报对象来做。
  • @Sossenbinder 那么序列化(或流)有问题,您的反序列化代码对我来说看起来非常好。您可以编辑问题并将序列化/写入文件部分添加吗?
  • 我添加了一个小提琴,展示了您发布的代码(或类似代码)的正确行为,所以显然还有其他问题您没有向我们展示
  • 谢谢。我将把文件路径放在内存流的哪里?
  • 你没有,我使用了MemoryStream,因为我使用网络小提琴进行演示(不允许写入磁盘),你应该使用FileStream正在做。 MemoryStreams 不写入文件(顾名思义),但基本相同(只是在内存中,而不是在磁盘上的文件中)
【解决方案2】:
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
                {

                }
            }
        }

【讨论】:

    【解决方案3】:

    看起来您只需在序列化之前将警报添加到警报列表中。这有效,似乎可以做你想做的事:

    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;
        }
    
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-03-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多