本文將介紹使用.NET自帶的序列化工具、Newtonsoft.json和ProtoBuf-Net來序列化一個成文件,對比文件大小。
初始化數據與數據模型
ProtoContract是ProtoBuf-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 |
對比之下的確是被縮減的很小