从二进制文件中读取序列化对象

时间:2015-02-03 19:25:34

标签: c# file serialization

我正在尝试将序列化对象写入和读取到二进制文件。我正在使用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())一样。

3 个答案:

答案 0 :(得分: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);
}

答案 1 :(得分:0)

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

    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,因为如果您继续追加它们,它将始终返回首先保存的集合。这应该是唯一的缺点。

答案 2 :(得分:0)

感谢您的帮助,我做到了。

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