本文将介绍使用.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 |
对比之下的确是被缩减的很小