【问题标题】:Reading serialized objects from binary file从二进制文件中读取序列化对象
【发布时间】:2015-04-03 03:10:23
【问题描述】:

我正在尝试将序列化对象写入和读取到二进制文件。我正在使用 Append FileMode 添加序列化对象,但是当我尝试读取文件时,它只打印一个反序列化对象。

这是我的序列化方法。

public void serialize(){ 
    MyObject obj = new MyObject();
    obj.n1 = 1;
    obj.n2 = 24;
    obj.str = "Some String";
    IFormatter formatter = new BinaryFormatter();
    Stream stream = new FileStream("MyFile.bin", FileMode.Append,                          FileAccess.Write, FileShare.None);
    formatter.Serialize(stream, obj);
    stream.Close()
}

这是我的反序列化方法。

public static void read()
{
    IFormatter formatter = new BinaryFormatter();
    Stream stream = new FileStream("MyFile.bin", FileMode.Open, FileAccess.Read, FileShare.Read);
    MyObject obj = (MyObject)formatter.Deserialize(stream);
    stream.Close();

    // Here's the proof.
    Console.WriteLine("n1: {0}", obj.n1);
    Console.WriteLine("n2: {0}", obj.n2);
    Console.WriteLine("str: {0}", obj.str);
}

我们如何遍历文件中的每条序列化记录,就像我们在 C++ 中使用 File.eof() 或 while(file.read()) 一样。

【问题讨论】:

    标签: c# file serialization


    【解决方案1】:

    Deserialize 只返回一个对象。您需要创建一个集合并循环,直到到达流的末尾:

    List<MyObject> list = new List<MyObject>();
    Stream stream = new FileStream("MyFile.bin", FileMode.Open, FileAccess.Read, FileShare.Read);
    while(stream.Position < stream.Length)
    {
         MyObject obj = (MyObject)formatter.Deserialize(stream);
         list.add(obj);
    }
    

    【讨论】:

    • 您需要序列化对象列表,以便反序列化返回相同的对象列表:dotnetperls.com/serialize-list
    • @user3290807 不确定你 - 你当然可以从流中读取连续的对象。它使反序列化更容易(因为您只是反序列化列表而不是循环),但这不是必需的。
    【解决方案2】:

    上面的解释是正确的,但是我会这样说,使用你喜欢的集合:

        public static void serializeIt()
        { 
            MyObject obj = new MyObject();
            obj.n1 = 1;
            obj.n2 = 24;
            obj.str = "Some String";
            MyObject obj2 = new MyObject();
            obj2.n1 = 1;
            obj2.n2 = 24;
            obj2.str = "Some other String";
            List<MyObject> list = new List<MyObject>();
            list.Add(obj);
            list.Add(obj2);
            IFormatter formatter = new BinaryFormatter();
            Stream stream = new FileStream("MyFile.bin", FileMode.Append,FileAccess.Write, FileShare.None);
            formatter.Serialize(stream, list);
            stream.Close();
        }
    
        public static void read()
        {
            IFormatter formatter = new BinaryFormatter();
            Stream stream = new FileStream("MyFile.bin", FileMode.Open, FileAccess.Read, FileShare.Read);
            List<MyObject> list = (List<MyObject>)formatter.Deserialize(stream);
            stream.Close();
    
        }
    

    您还应该确保每次序列化集合时都重写 MyFile.bin,因为如果您继续附加它们,它总是会返回首先保存的集合。这应该是唯一的缺点。

    【讨论】:

      【解决方案3】:

      谢谢你的帮助,我做了这个。

          using System.IO;
          using System.Runtime.Serialization.Formatters.Binary;
      
          private static Dictionary<int, ArrayList> J1_CarteDeck;
      
          private static string PathDocuments = String.Format("{0}\\Antize Game\\", Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments));
          private const string FILE_NAME      = "Antize.data";
      
         public static bool SauvegarderDeck()
         {
             if (!(Directory.Exists(PathDocuments)))
                 Directory.CreateDirectory(PathDocuments);
      
             if (File.Exists(PathDocuments + FILE_Deck))
                 File.Delete(PathDocuments + FILE_Deck);
      
             foreach (ArrayList child in J1_CarteDeck.Values)
             {  
                 if(child != null)
                 { 
                      BinaryFormatter formatter   = new BinaryFormatter();
                      FileStream stream           = new FileStream(PathDocuments + FILE_Deck, FileMode.Append, FileAccess.Write, FileShare.None);
                      formatter.Serialize(stream, child);
                      stream.Close();
                  }
              }
      
              if (File.Exists(PathDocuments + FILE_Deck))
                  return true;
              else
                  return false;
          }
      
          public static bool ChargerDeck()
          {
              if (!(File.Exists(PathDocuments + FILE_Deck)))
                  return false;
      
              int cptr = 1;
      
              J1_CarteDeck                = new Dictionary<int, ArrayList>();
      
              BinaryFormatter formatter   = new BinaryFormatter();
              Stream stream               = new FileStream(PathDocuments + FILE_Deck, FileMode.Open, FileAccess.Read, FileShare.None);
      
              while (stream.Position < stream.Length)
              {
                  J1_CarteDeck[cptr] = (ArrayList)formatter.Deserialize(stream);
                  cptr++;
              }
      
              stream.Close();
      
              return true;
          }
      

      【讨论】:

      • 请提供更具体的答案,而不仅仅是一些代码行
      【解决方案4】:

      简单地遍历二进制文件中的每个对象

      using (System.IO.FileStream fs = new System.IO.FileStream("D:\\text\\studentdata.txt", System.IO.FileMode.Open, System.IO.FileAccess.Read))
              {
                  System.Runtime.Serialization.Formatters.Binary.BinaryFormatter sf = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();
                  Object o = sf.Deserialize(fs);
                  while (fs.Position < fs.Length)
                  {
                      o = sf.Deserialize(fs);
                      Student student = (o as Student);
                      Console.WriteLine("str: {0}", student.sname);
                  }
              }
      

      【讨论】:

      • 您的答案可以通过额外的支持信息得到改进。请edit 添加更多详细信息,例如引用或文档,以便其他人可以确认您的答案是正确的。你可以找到更多关于如何写好答案的信息in the help center
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-01-19
      相关资源
      最近更新 更多