【问题标题】:What is a good way to serialize/deserialize lists of structs to/from binary?将结构列表序列化/反序列化到二进制文件的好方法是什么?
【发布时间】:2017-05-01 09:15:45
【问题描述】:

我正在为反恐精英开发一个热图工具。 我使用 [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# 和编程新手。 我在这方面的表现超出了我的水平,因为我没有给自己足够的时间来正确地学习如何去做。这两天我一直在努力尝试实现它,但我陷入了各种各样的错误中,我认为我的方法完全错误。

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

谢谢!

【问题讨论】:

  • JSON 对你有好处:newtonsoft.com/json 那里有很多代码示例。
  • 为什么必须将数据保存为二进制数据? JSON还不够吗?见@trailmax 链接
  • 老实说,我不知道为什么它应该是二进制的,我在 2 天前才了解序列化,二进制序列化是我的切入点。我会查看提供的链接,谢谢!

标签: c# list serialization struct


【解决方案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());
    }
    

【讨论】:

  • 我知道 cmets 应该是关于进一步的问题和更正,但我真的要感谢您花时间帮助我。多么详尽和清晰的解释!我找到了一种通过 JSON 使其工作的方法,但我也会研究数据库方法,因为在不久的将来我需要这些知识。谢谢!
【解决方案2】:

您可以将其序列化为 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

【讨论】:

  • 您好,感谢您的意见!我会研究 Json,看看我能不能搞定。
猜你喜欢
  • 2014-11-28
  • 2014-01-04
  • 1970-01-01
  • 2015-02-12
  • 1970-01-01
  • 2011-01-14
  • 2014-01-20
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多