.NET序列化-二進制與Json

本文將介紹使用.NET自帶的序列化工具、Newtonsoft.jsonProtoBuf-Net來序列化一個成文件,對比文件大小。

初始化數據與數據模型

ProtoContractProtoBuf-Net需要序列化元素的特性,Serializable則是自帶的Json等需要的特性,同時注意需要申明屬性爲public

using ProtoBuf;
using System;

namespace BinarySerialize
{
    [Serializable, ProtoContract]
    public class SerializeData
    {
        [ProtoMember(1)]
        public int TmplateType;
        [ProtoMember(2)]
        public int TeplateID;
        [ProtoMember(3)]
        public string Name;
        [ProtoMember(4)]
        public int Group;
        [ProtoMember(5)]
        public float Duration;
        [ProtoMember(6)]
        public bool Loop;

    }
    [Serializable, ProtoContract]
    public class DataContainer
    {
        [ProtoMember(1)]
        public SerializeData[] EventTemplateArray;
    }
}

這裏有個坑就是上面的代碼中,涉及到了嵌套消息,在一個類中封裝了另一個類,這裏有很多坑,最開始我在外層類中直接new了數組的大小,而不是現在的申明,如果直接new了大小,那麼最後在ProtoBuf-Net反序列化回來後會發現讀了兩倍於我們開的大小,它在做反序列化時,又給我們開了內存,而且這一部分內存是null,沒有東西。然後我就改成了在Init裏面開內存,在類裏只申明,如下面初始化函數中開的1024個大小的數組空間。
初始化函數

public static DataContainer Init()
{
    DataContainer Container = new DataContainer();
    Container.EventTemplateArray = new SerializeData[1024];
    for (int i = 0; i < 1024; i++)
    {
        Container.EventTemplateArray[i] = new SerializeData();
        Container.EventTemplateArray[i].TmplateType = i;
        Container.EventTemplateArray[i].TeplateID = i;
        Container.EventTemplateArray[i].Name = i.ToString();
        Container.EventTemplateArray[i].Loop = true;
        Container.EventTemplateArray[i].Group = i;
        Container.EventTemplateArray[i].Duration = i;
    }
    return Container;
}

主函數

    static void Main(string[] args)
    {
        DataContainer DC =  Init();
        //序列化
        JsonSerialze(DC);
        BinarySerialize("Binaryfile.bin",DC);
        ProtoBufSerialize("ProtoBufFile.bin", DC);
        Test();
        //反序列化
        DataContainer DC2 = JsonDeserialize();
        DC2 = BinaryDeSerialize("Binaryfile.bin");
        DC2 = ProtoBufDeSerialize("ProtoBufFile.bin");
        Console.ReadKey();
    }

Json

使用了Newtonsoft.Json來序列化我們的Json,安裝方法是在VS的NuGet包管理下載即可。
或者使用命令:Install-Package Newtonsoft.Json

   //Json序列化
   public static void JsonSerialze(DataContainer data)
    {
        string json = JsonConvert.SerializeObject(data);
        Write("jsonfile.json", json);
    }
    //Json反序列化
    public static DataContainer JsonDeserialize()
    {
        string json = Read("jsonfile.json");
        DataContainer DC = JsonConvert.DeserializeObject<DataContainer>(json);
        return DC;
    }
    public static void Write(string filename, string str)
    {
        try
        {
            using (StreamWriter SW = new StreamWriter(System.IO.Directory.GetCurrentDirectory()+ filename, false))
            {
                SW.Write(str);
            }
            Console.WriteLine("Write To Show.txt succese");
        }
        catch(Exception ex)
        {
            Console.WriteLine(ex);
        }
    }
    public static string Read(string path)
    {
        string json = string.Empty;
        string line;
        using (StreamReader SR = new StreamReader(Directory.GetCurrentDirectory()+ path))
        {
            if ((line = SR.ReadLine()) != null)
            {
                json += line;
            }
        }
        return json;
    }

自帶BinaryFormatter

序列化與反序列化函數

    public static void BinarySerialize(string name, DataContainer data)
    {
        using (FileStream fs = new FileStream(Directory.GetCurrentDirectory() + name, FileMode.OpenOrCreate, FileAccess.Write))
        {
            BinaryFormatter BF = new BinaryFormatter();
            try
            {
                BF.Serialize(fs, data);
            }
            catch(Exception ex)
            {
                Console.WriteLine(ex);
            }
        }
    }
            public static DataContainer BinaryDeSerialize(string name)
    {
        DataContainer DC = null;
        using (FileStream fs = new FileStream(Directory.GetCurrentDirectory() + name, FileMode.OpenOrCreate, FileAccess.Read))
        {
            BinaryFormatter BF = new BinaryFormatter();
            try
            {
                DC = BF.Deserialize(fs) as DataContainer;
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex);
            }
        }
        return DC;
    }

ProtoBuf-Net

它的安裝:
在VS的NuGet包管理器裏面搜索就可以下載,然後勾選安裝的本項目即可。
ProtoBuf-Net的Github上面有介紹一些基本的使用方法以及一些支持的數據結構,比如我測試的數組類型也是支持的:

private static void Test()
        {
            SerializeData[] tmp = new SerializeData[2];
            for (int i = 0; i < 2; i++)
            {
                tmp[i] = new SerializeData
                {
                    TmplateType = i,
                    TeplateID = i,
                    Name = i.ToString(),
                    Loop = true,
                    Group = i,
                    Duration = i
                };
            }
            SerializeData[] tmp2;
            try
            {
                using (FileStream fs = new FileStream("Test.bin", FileMode.OpenOrCreate, FileAccess.ReadWrite))
                {
                    ProtoBuf.Serializer.Serialize<SerializeData[]>(fs, tmp);
                }
                //不可使用同一個流
                using (FileStream fs = new FileStream("Test.bin", FileMode.OpenOrCreate, FileAccess.ReadWrite))
                {
                    tmp2 = Serializer.Deserialize<SerializeData[]>(fs);
                }     
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex);
            }
        }

序列化與反序列化函數

    public static void ProtoBufSerialize(string filename, DataContainer data)
    {
        
        try
        {
            using (FileStream fs = new FileStream(Directory.GetCurrentDirectory()+filename, FileMode.OpenOrCreate, FileAccess.ReadWrite))
            {
                ProtoBuf.Serializer.Serialize<DataContainer>(fs, data);
                //DataContainer tmp = Serializer.Deserialize<DataContainer>(fs);
                fs.Close();
            }
        }
        catch(Exception ex)
        {
            Console.WriteLine(ex);
        }
    }
            public static DataContainer ProtoBufDeSerialize(string filename)
    {
        DataContainer DC = null;
        try
        {
            using (FileStream fs = new FileStream(Directory.GetCurrentDirectory()+filename, FileMode.Open, FileAccess.ReadWrite))
            {
                DC = ProtoBuf.Serializer.Deserialize<DataContainer>(fs);
                fs.Close();
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex);
        }
        return DC;
    }

文件大小對比

FileName Size
Debugjsonfile 90K
DebugBinaryfile 41K
DebugProtoBufFile 23K

對比之下的確是被縮減的很小

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章