从二进制文件序列化/反序列化结构列表的好方法是什么?

时间:2017-05-01 09:15:45

标签: c# list serialization struct

我正在开发一种用于反击的热图工具。 我使用[serializable]结构来描述这样的游戏内事件:

[Serializable]
public struct KillEvent
{
    public float killerPosX;
    public float killerPosY;
    public float victimPosX;
    public float victimPosY;
    public string killerSide;
    public string victimSide;
    public string weaponType;
}

这个描述了游戏中的杀戮事件。

每场比赛都有大约200次杀戮(以及我不会提及的其他内容),我将其放入列表中,如下所示:

List<KillEvent> listOfKills

我有12个类似的列表,我想写一个二进制文件,以便存档特定的反击符合以供以后使用。

然后我想反序列化二进制文件并检索列表。

我是C#的新手并完全编程。 因为我还没有给自己足够的时间来正确地学习如何去做,所以我的拍摄水平高于我的水平。两天来,我一直在抨击我的努力,试图让它成为现实,但我陷入各种各样的错误中,我认为我的方法完全是错误的。

问题: 对于我上面描述的内容,什么是合理的方法? 感谢任何输入,但由于我缺乏经验,代码或伪代码甚至更好。

谢谢!

2 个答案:

答案 0 :(得分:1)

你可以将它序列化为Json作为评论提到 但如果你真的需要将其序列化为二进制文件你可以使用Binaryformatter 这是如何使用的示例

using System.IO;
using System.Runtime.Serialization.Formatters.Binary;

    void Serialize(string path, KillEvent ev)
    {
        FileStream fs = new FileStream(path, FileAccess.ReadWrite, FileMode.OpenOrCreate, FileShare.None);
        BinaryFormatter bf = new BinaryFormatter();
        bf.Serialize(fs, ev);
    }

并查看更多内容 https://msdn.microsoft.com/en-us/library/system.runtime.serialization.formatters.binary.binaryformatter(v=vs.110).aspx

答案 1 :(得分:1)

使用二进制序列化而不是数据库来存储应该在数据库中的数据是一个坏主意,二进制序列化也很慢。

因此,您确实需要将此类数据存储在数据库中;因为你是C#的新手,我认为我应该花几分钟时间组合一个展示它的small sample Entity Framework database using local DB。使用VS2013和VS2015进行测试,以显示可以轻松完成此操作。

要添加到现有项目,以下内容应该有效。

  1. 确保您引用EntityFramework(package.config)

    <packages>
        <package id="EntityFramework" version="6.1.3" targetFramework="net452" />
    </packages>
    
  2. 添加一个派生自DbContext的类,该类是数据存储的接口

    using System;
    using System.ComponentModel.DataAnnotations;
    using System.Data.Entity;
    
    public class Data : DbContext
    {
        // Your context has been configured to use a 'Data' connection string from your application's
        // configuration file (App.config or Web.config). By default, this connection string targets the
        // 'db_demo.Data' database on your LocalDb instance.
        //
        // If you wish to target a different database and/or database provider, modify the 'Data'
        // connection string in the application configuration file.
        public Data()
            : base("name=Data")
        {
        }
    
        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
        }
    
        public virtual DbSet<KillEvent> KillEvents { get; set; }
    }
    
    [Serializable]
    public class KillEvent
    {
        [Key]
        public int KillEventId { get; set; }
    
        public float killerPosX { get; set; }
        public float killerPosY { get; set; }
        public float victimPosX { get; set; }
        public float victimPosY { get; set; }
        public string killerSide { get; set; }
        public string victimSide { get; set; }
        public string weaponType { get; set; }
    
        public override string ToString()
        {
            return String.Format("Id{0,6}: Side {1}, weapon {2}, pos ({3},{4}) victim  side {5} pos ({6},{7}) ",
                KillEventId,
                killerSide,
                weaponType,
                killerPosX,
                killerPosY,
                victimSide,
                victimPosX, victimPosY
                );
        }
    }
    
  3. 创建测试数据的测试方法

    var db = new Data();
    var rng = new Random();
    if (!db.KillEvents.Any())
    {
        System.Console.WriteLine("Populating with test data");
        for (var i = 0; i < 100; i++)
        {
            var data = new KillEvent()
            {
                killerPosX = rng.Next(0, 1000),
                killerPosY = rng.Next(0, 1000),
                killerSide = rng.Next(0, 3).ToString(),
                victimPosX = rng.Next(0, 1000),
                victimPosY = rng.Next(0, 1000),
                victimSide = rng.Next(0, 3).ToString(),
                weaponType = "AIM-" + (9 + Math.Round((int)rng.Next(0, 2) * 111.0)).ToString(),
            };
            db.KillEvents.Add(data);
            db.SaveChanges();
        }
    }
    
  4. 转储数据的方法

    var db1 = new Data();
    foreach (var ke in db1.KillEvents)
    {
        System.Console.WriteLine("Ke {0}", ke.ToString());
    }
    
  5. 使用LINQ

    提取数据的方法
    var db1 = new Data();
    foreach (var groupedBySide in db1.KillEvents.GroupBy(xx=>xx.killerSide))
    {
        System.Console.WriteLine("Side {0} has {1} kills ", groupedBySide.Key, groupedBySide.Count());
    }