Unity/C# Xml序列化 与 二进制序列化

Posted ssuper41

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Unity/C# Xml序列化 与 二进制序列化相关的知识,希望对你有一定的参考价值。

序列化与反序列化

一、前言

游戏里,我们经常遇到这种情景:要保存一些数据为文件,方便运行时再次读取使用。这就涉及到了序列化与反序列化

二、说明

1、什么是序列化/反序列化

  • 序列化:通常的来讲,就是把 对象 转成 二进制序列。可以简单的理解为把对象转成一个文件
  • 反序列化:反序列化是序列化的相反操作。可以简单的理解为,是把文件转为对象的这么一个过程

2、序列化有几种方式

  • 游戏中常见的序列化方法有 二进制序列化,Xml序列化, Json序列化等等。
  • 接下来讲一下 二进制序列化和Xml序列化的具体操作

三、实际操作

1、准备操作

1.1、定义2个测试类

既然是需要把对象序列化为xml文件,那么为了方便测试,这里定义2个测试类

[System.Serializable]
public class Model

    
    //使用[XmlAttribute]特性,生成的xml标签等于该字段名‘val1’
    [XmlAttribute]
    public int Val1;
    
        
    //使用[XmlAttribute]特性,并指定生成的xml标签等于‘Val2-alias’,而不是默认的字段名
    [XmlAttribute("Val2-alias")]
    public int Val2;

    //list字段 需要使用[XmlElement]特性,并起别名为ModelItem
    [XmlElement("ModelItem")] 
    public List<ModelItem> itemList;



[System.Serializable]
public class ModelItem

    [XmlAttribute]
    public int id;

1.2、构建model测试类

接下来,我们用一个方法,来创建Model类,并为其填充一些测试数据。

    /// <summary>
    /// 返回一个测试model对象
    /// </summary>
    /// <returns></returns>
    Model BuildModel()
    
        Model model = new Model();
        model.Val1 = 1;
        model.Val2 = 2;
        ModelItem modelItem1 = new ModelItem();
        modelItem1.id = 123;
        ModelItem modelItem2 = new ModelItem();
        modelItem2.id = 456;
        
        model.itemList = new List<ModelItem>();
        model.itemList.Add(modelItem1);
        model.itemList.Add(modelItem2);
        return model;
    

2、Xml篇

2.1、Xml序列化

    /// <summary>
    /// 序列化
    /// </summary>
    void Test_XmlSerializ()
    
        //构建model对象
        Model model = BuildModel();
        
        //执行序列化到文件的操作
        FileStream fs = new FileStream(Application.dataPath+"/Resources/model.xml",FileMode.OpenOrCreate,FileAccess.ReadWrite,FileShare.ReadWrite);
        StreamWriter sw = new StreamWriter(fs,Encoding.UTF8);
        XmlSerializer xs = new XmlSerializer(typeof(Model));
        xs.Serialize(sw,model);
        
        //关闭文件流
        sw.Close();
        fs.Close();
    
  • 生成的文件如下,可以看到成功的生成了文件,数据也是跟我们定义的一样

2.2、Xml反序列化

2.2.1、Xml反序列化-通过文件流

  • Xml反序列化有两种方法。其一,通过文件流
    /// <summary>
    /// 反序列化-通过文件流
    /// </summary>
    void Test_XmlDeserialize_By_FileStream()
    
    	//传入文件路径:Application.dataPath+"/Resources/model.xml",构建文件流
        FileStream fs = new FileStream(Application.dataPath+"/Resources/model.xml",FileMode.OpenOrCreate,FileAccess.ReadWrite,FileShare.ReadWrite);
        StreamReader sr = new StreamReader(fs,Encoding.UTF8);
        XmlSerializer xs = new XmlSerializer(typeof(Model));
        Model model = xs.Deserialize(sr) as Model;
        sr.Close();
        fs.Close();
        
        Debug.Log($"model.Val1:model.Val1  model.Val2:model.Val2  item1Id:model.itemList[0].id  item2Id:model.itemList[1].id");
    
    //打印如下
    //model.Val1:1  model.Val2:2  item1Id:123  item2Id:456

2.2.1、Xml反序列化-通过字符串文本

  • 通过字符串来反序列化
  • 有时我们的Xml文件是放在Resources目录下的,好比上面生成的文件就在这个目录下。Resources目录下的文件在真正出包后,用纯路径是获取不到这个文件的,所以没办法用文件流来反序列化。那这种情况怎么读取呢,可以使用Resources.Load() 把字符串文本读出来,然后使用 字符串文本反序列化的方式。代码如下
    /// <summary>
    /// 反序列化-通过字符串文本
    /// </summary>
    void Test_XmlDeserialize_By_String()
    
    	//读取Resources/model.xml文件
        TextAsset textAsset = Resources.Load<TextAsset>("model");
        StringReader sr = new StringReader(textAsset.text);
        XmlSerializer xs = new XmlSerializer(typeof(Model));
                    
        Model model = xs.Deserialize(sr) as Model;
        Debug.Log($"model.Val1:model.Val1  model.Val2:model.Val2  item1Id:model.itemList[0].id  item2Id:model.itemList[1].id");
    
    //打印如下
    //model.Val1:1  model.Val2:2  item1Id:123  item2Id:456

3、二进制篇

3.1、二进制序列化

    void Test_ByteSerialize()
    
        //构建model类
        Model model = BuildModel();
        
        BinaryFormatter bf = new BinaryFormatter();
        FileStream fs = new FileStream(Application.dataPath+"/Resources/model.byte",FileMode.OpenOrCreate,FileAccess.ReadWrite,FileShare.ReadWrite);
        bf.Serialize(fs,model);
        fs.Close();
    
  • 截图
    可以看到成功的生成了model.byte文件

3.2、二进制反序列化

    void Test_ByteDeserialize()
    
        BinaryFormatter bf = new BinaryFormatter();
        FileStream fs = new FileStream(Application.dataPath+"/Resources/model.byte",FileMode.OpenOrCreate,FileAccess.ReadWrite,FileShare.ReadWrite);
        Model model = bf.Deserialize(fs) as Model;
        Debug.Log($"model.Val1:model.Val1  model.Val2:model.Val2  item1Id:model.itemList[0].id  item2Id:model.itemList[1].id");
    
    //打印如下
    //model.Val1:1  model.Val2:2  item1Id:123  item2Id:456

Apache Avro 序列化与反序列化 (Java 实现)

像两个交流一样要找一个互相能理解的语言, 在国内为普通话, 跑国外多用英语相通, 两个进程间通信也需要找一个大家都能理解的数据格式. 简单的如 JSON, XML, 那是自我描述性格式, XML 有 Schema 定义, 但尚无正式的 JSON Schema 规范. 在讲求效率的场合, 纯文本式的数据交换格式无法满足要求, 于是有二进制的 Google Protobuf 和 Apache Avro. 在 Apache 的生态像 Hadoop, Kafka 中自然是选用 Avro.

Avro 支持多种语言, 如 C, C++, C#, Java, PHP, Python 和 Ruby. 它使用 JSON 来定义 Schema, 通过工具可以由 Schema 生成相应语言的数据对象, 比如 Java 的  avro-tools.jar. 这样可以在跨进程跨语言透明的实现为对象交换.

本文体验 Java 环境中 Avro 数据格式的序列化与反序列化.

Avro Schema 文件就是数据生产和消费端的通信协议; 我们可以由 Schema 生成相应的 Java 对象, 然后以具体的 Java 对象交换, 或者不生成 Java 对象而纯粹以 GenericRecord 交互. 为操作数据的简单, 我们通常采用前一种方式, 即生成具体数据传输对象. 阅读全文 >>


以上是关于Unity/C# Xml序列化 与 二进制序列化的主要内容,如果未能解决你的问题,请参考以下文章

Java 序列化与反序列化

Apache Avro 序列化与反序列化 (Java 实现)

是否存在可二进制序列化的 XML 特定对象(如 XElement)?

(VIP-朝夕教育)2021-05-30 .NET高级班 20-序列化反序列化(XML,Json,二进制,soap)

序列化与反序列化存储updatepanel

XML