C# 如何序列化/反序列化列表<;类对象>;用protobuf?
我想序列化C# 如何序列化/反序列化列表<;类对象>;用protobuf?,c#,serialization,protocol-buffers,protobuf-net,C#,Serialization,Protocol Buffers,Protobuf Net,我想序列化列表 我读过这篇文章,但仍然找不到解决办法。如何对其进行序列化和反序列化 我的类和结构: [Serializable, ProtoContract(Name = @"Archive"), ProtoInclude(1, typeof(List<ArchiveData>))] public partial class Archive : IExtensible { [ProtoMember(1, IsRequired = true, OverwriteList = t
列表
我读过这篇文章,但仍然找不到解决办法。如何对其进行序列化和反序列化
我的类和结构:
[Serializable, ProtoContract(Name = @"Archive"), ProtoInclude(1, typeof(List<ArchiveData>))]
public partial class Archive : IExtensible
{
[ProtoMember(1, IsRequired = true, OverwriteList = true, Name = @"data", DataFormat = DataFormat.Default)]
public List<ArchiveData> data { get; set; }
public Archive()
{
data = new List<ArchiveForm.ArchiveData>();
}
private IExtension extensionObject;
IExtension IExtensible.GetExtensionObject(bool createIfMissing)
{
return Extensible.GetExtensionObject(ref extensionObject, createIfMissing);
}
}
public struct ArchiveData
{
[ProtoMember(1, IsRequired = false, OverwriteList = true, Name = @"sourcefolder", DataFormat = DataFormat.Default)]
[global::System.ComponentModel.DefaultValue("")]
public string sourcefolder { get; set; }
[ProtoMember(2, IsRequired = false, OverwriteList = true, Name = @"destinationfolder", DataFormat = DataFormat.Default)]
[global::System.ComponentModel.DefaultValue("")]
public string destinationfolder { get; set; }
[ProtoMember(3, IsRequired = false, OverwriteList = true, Name = @"period", DataFormat = DataFormat.FixedSize)]
[global::System.ComponentModel.DefaultValue((int)0)]
public int period { get; set; }
public ArchiveData(string sfolder = "", string dfolder = "", int priod = 0)
{
sourcefolder = sfolder;
destinationfolder = dfolder;
period = priod;
}
}
------------------------------编辑------------------------------
已添加此部分以获取更多信息。当我像下面的代码一样使用SerializeWithLengthPrefix/DeserializeWithLengthPrefix函数时,对于我使用反序列化函数的第一个类,它每次都能正常工作。但是对于我使用反序列化函数的第二个类,它返回null
[Serializable, ProtoContract(Name = @"OptionData")]
public class OptionData : IExtensible
{
[ProtoMember(1, IsRequired = false, OverwriteList = true, Name = @"StartWithWindows", DataFormat = DataFormat.Default)]
[DefaultValue(false)]
public bool StartWithWindows { get; set; }
[ProtoMember(2, IsRequired = false, OverwriteList = true, Name = @"AutoBackup", DataFormat = DataFormat.Default)]
[DefaultValue(false)]
public bool AutoBackup { get; set; }
[ProtoMember(3, IsRequired = false, OverwriteList = true, Name = @"Speed", DataFormat = DataFormat.FixedSize)]
[DefaultValue((int)0)]
public int Speed { get; set; }
private IExtension extensionObject;
IExtension IExtensible.GetExtensionObject(bool createIfMissing)
{
return Extensible.GetExtensionObject(ref extensionObject, createIfMissing);
}
}
public static void Update(OptionData op)
{
using (var fs = File.Create(probuffile))
{
Serializer.SerializeWithLengthPrefix(fs, op, PrefixStyle.Base128, 3);
}
}
public static void Update(Archive arc)
{
using (var fs = File.Create(probuffile))
{
Serializer.SerializeWithLengthPrefix<Archive>(fs, arc, PrefixStyle.Base128, 2);
}
}
public static void Refresh(ref OptionData op)
{
if (File.Exists(probuffile))
{
using (var fs = File.OpenRead(probuffile))
{
op = Serializer.DeserializeWithLengthPrefix<OptionData>(fs, PrefixStyle.Base128, 3);
}
}
}
public static void Refresh(ref Archive arc)
{
if (File.Exists(probuffile))
{
using (var fs = File.OpenRead(probuffile))
{
arc = Serializer.DeserializeWithLengthPrefix<Archive>(fs, PrefixStyle.Base128, 2);
}
}
}
[可序列化,协议(名称=@“OptionData”)]
公共类选项数据:可扩展
{
[ProtoMember(1,IsRequired=false,OverwriteList=true,Name=@“StartWithWindows”,DataFormat=DataFormat.Default)]
[默认值(false)]
公共bool StartWithWindows{get;set;}
[ProtoMember(2,IsRequired=false,OverwriteList=true,Name=@“AutoBackup”,DataFormat=DataFormat.Default)]
[默认值(false)]
公共布尔自动备份{get;set;}
[ProtoMember(3,IsRequired=false,OverwriteList=true,Name=@“Speed”,DataFormat=DataFormat.FixedSize)]
[默认值((int)0)]
公共整数速度{get;set;}
私有IExtension扩展对象;
IExtension IExtensible.GetExtensionObject(bool createIfMissing)
{
返回Extensible.GetExtensionObject(ref extensionObject,createIfMissing);
}
}
公共静态无效更新(OptionData op)
{
使用(var fs=File.Create(probuffile))
{
Serializer.SerializeWithLengthPrefix(fs,op,PrefixStyle.Base128,3);
}
}
公共静态无效更新(存档弧)
{
使用(var fs=File.Create(probuffile))
{
Serializer.SerializeWithLengthPrefix(fs,arc,PrefixStyle.Base128,2);
}
}
公共静态无效刷新(参考OptionData op)
{
if(File.Exists(probuffile))
{
使用(var fs=File.OpenRead(probuffile))
{
op=Serializer.DeserializeWithLengthPrefix(fs,PrefixStyle.Base128,3);
}
}
}
公共静态无效刷新(参考存档弧)
{
if(File.Exists(probuffile))
{
使用(var fs=File.OpenRead(probuffile))
{
arc=Serializer.DeserializeWithLengthPrefix(fs,PrefixStyle.Base128,2);
}
}
}
我很乐意提供帮助,但我正努力让它失败。您说“但它几乎总是失败”,但以下可运行控制台exer工作正常,并写入各种大小的大范围数据:
using ProtoBuf;
using System;
using System.Collections.Generic;
using System.IO;
static class P
{
static void Main()
{
var random = new Random(12345);
// start with 100
var archive = CreateData(random, 100);
Update(archive);
Refresh(ref archive);
// make it bigger
archive = CreateData(random, 200);
Update(archive);
Refresh(ref archive);
// make it smaller
archive = CreateData(random, 50);
Update(archive);
Refresh(ref archive);
// go wild
for (int i = 0; i < 1000; i++)
{
archive = CreateData(random, random.Next(0, 500));
Update(archive);
Refresh(ref archive);
}
}
static Archive CreateData(Random random, int dataCount)
{
var archive = new Archive();
var data = archive.data;
for (int i = 0; i < dataCount; i++)
{
data.Add(new ArchiveData
{
period = random.Next(10000),
sourcefolder = CreateString(random, 50),
destinationfolder = CreateString(random, 50)
});
}
return archive;
}
private static unsafe string CreateString(Random random, int maxLength)
{
const string Alphabet = "abcdefghijklmnopqrstuvwxyz0123456789";
int len = random.Next(maxLength + 1);
char* chars = stackalloc char[len];
for (int i = 0; i < len; i++)
{
chars[i] = Alphabet[random.Next(Alphabet.Length)];
}
return new string(chars, 0, len);
}
static string probuffile = "my.bin";
public static void Refresh(ref Archive arc)
{
if (File.Exists(probuffile))
{
using (var fs = File.OpenRead(probuffile))
{
arc = Serializer.Deserialize<Archive>(fs);
Console.WriteLine("Read: {0} items, {1} bytes", arc.data.Count, fs.Length);
}
}
}
public static void Update(Archive arc)
{
using (var fs = File.Create(probuffile))
{
Serializer.Serialize<Archive>(fs, arc);
fs.SetLength(fs.Position);
Console.WriteLine("Wrote: {0} items, {1} bytes", arc.data.Count, fs.Length);
}
}
}
[Serializable, ProtoContract(Name = @"Archive"), ProtoInclude(1, typeof(List<ArchiveData>))]
public partial class Archive : IExtensible
{
[ProtoMember(1, IsRequired = true, OverwriteList = true, Name = @"data", DataFormat = DataFormat.Default)]
public List<ArchiveData> data { get; set; }
public Archive()
{
data = new List<ArchiveData>();
}
private IExtension extensionObject;
IExtension IExtensible.GetExtensionObject(bool createIfMissing)
{
return Extensible.GetExtensionObject(ref extensionObject, createIfMissing);
}
}
[ProtoContract]
public struct ArchiveData
{
[ProtoMember(1, IsRequired = false, OverwriteList = true, Name = @"sourcefolder", DataFormat = DataFormat.Default)]
[global::System.ComponentModel.DefaultValue("")]
public string sourcefolder { get; set; }
[ProtoMember(2, IsRequired = false, OverwriteList = true, Name = @"destinationfolder", DataFormat = DataFormat.Default)]
[global::System.ComponentModel.DefaultValue("")]
public string destinationfolder { get; set; }
[ProtoMember(3, IsRequired = false, OverwriteList = true, Name = @"period", DataFormat = DataFormat.FixedSize)]
[global::System.ComponentModel.DefaultValue((int)0)]
public int period { get; set; }
public ArchiveData(string sfolder = "", string dfolder = "", int priod = 0)
{
sourcefolder = sfolder;
destinationfolder = dfolder;
period = priod;
}
}
使用ProtoBuf;
使用制度;
使用System.Collections.Generic;
使用System.IO;
静态P类
{
静态void Main()
{
var random=新随机(12345);
//从100开始
var archive=CreateData(随机,100);
更新(档案);
刷新(参考档案);
//把它弄大点
存档=创建数据(随机,200);
更新(档案);
刷新(参考档案);
//小一点
存档=创建数据(随机,50);
更新(档案);
刷新(参考档案);
//发狂
对于(int i=0;i<1000;i++)
{
archive=CreateData(随机,random.Next(0500));
更新(档案);
刷新(参考档案);
}
}
静态归档CreateData(随机、int-dataCount)
{
var archive=new archive();
var data=archive.data;
对于(int i=0;iArchive archive = new Archive();
//Add some ArchiveData.
Refresh(ref archive);
[Serializable, ProtoContract(Name = @"OptionData")]
public class OptionData : IExtensible
{
[ProtoMember(1, IsRequired = false, OverwriteList = true, Name = @"StartWithWindows", DataFormat = DataFormat.Default)]
[DefaultValue(false)]
public bool StartWithWindows { get; set; }
[ProtoMember(2, IsRequired = false, OverwriteList = true, Name = @"AutoBackup", DataFormat = DataFormat.Default)]
[DefaultValue(false)]
public bool AutoBackup { get; set; }
[ProtoMember(3, IsRequired = false, OverwriteList = true, Name = @"Speed", DataFormat = DataFormat.FixedSize)]
[DefaultValue((int)0)]
public int Speed { get; set; }
private IExtension extensionObject;
IExtension IExtensible.GetExtensionObject(bool createIfMissing)
{
return Extensible.GetExtensionObject(ref extensionObject, createIfMissing);
}
}
public static void Update(OptionData op)
{
using (var fs = File.Create(probuffile))
{
Serializer.SerializeWithLengthPrefix(fs, op, PrefixStyle.Base128, 3);
}
}
public static void Update(Archive arc)
{
using (var fs = File.Create(probuffile))
{
Serializer.SerializeWithLengthPrefix<Archive>(fs, arc, PrefixStyle.Base128, 2);
}
}
public static void Refresh(ref OptionData op)
{
if (File.Exists(probuffile))
{
using (var fs = File.OpenRead(probuffile))
{
op = Serializer.DeserializeWithLengthPrefix<OptionData>(fs, PrefixStyle.Base128, 3);
}
}
}
public static void Refresh(ref Archive arc)
{
if (File.Exists(probuffile))
{
using (var fs = File.OpenRead(probuffile))
{
arc = Serializer.DeserializeWithLengthPrefix<Archive>(fs, PrefixStyle.Base128, 2);
}
}
}
using ProtoBuf;
using System;
using System.Collections.Generic;
using System.IO;
static class P
{
static void Main()
{
var random = new Random(12345);
// start with 100
var archive = CreateData(random, 100);
Update(archive);
Refresh(ref archive);
// make it bigger
archive = CreateData(random, 200);
Update(archive);
Refresh(ref archive);
// make it smaller
archive = CreateData(random, 50);
Update(archive);
Refresh(ref archive);
// go wild
for (int i = 0; i < 1000; i++)
{
archive = CreateData(random, random.Next(0, 500));
Update(archive);
Refresh(ref archive);
}
}
static Archive CreateData(Random random, int dataCount)
{
var archive = new Archive();
var data = archive.data;
for (int i = 0; i < dataCount; i++)
{
data.Add(new ArchiveData
{
period = random.Next(10000),
sourcefolder = CreateString(random, 50),
destinationfolder = CreateString(random, 50)
});
}
return archive;
}
private static unsafe string CreateString(Random random, int maxLength)
{
const string Alphabet = "abcdefghijklmnopqrstuvwxyz0123456789";
int len = random.Next(maxLength + 1);
char* chars = stackalloc char[len];
for (int i = 0; i < len; i++)
{
chars[i] = Alphabet[random.Next(Alphabet.Length)];
}
return new string(chars, 0, len);
}
static string probuffile = "my.bin";
public static void Refresh(ref Archive arc)
{
if (File.Exists(probuffile))
{
using (var fs = File.OpenRead(probuffile))
{
arc = Serializer.Deserialize<Archive>(fs);
Console.WriteLine("Read: {0} items, {1} bytes", arc.data.Count, fs.Length);
}
}
}
public static void Update(Archive arc)
{
using (var fs = File.Create(probuffile))
{
Serializer.Serialize<Archive>(fs, arc);
fs.SetLength(fs.Position);
Console.WriteLine("Wrote: {0} items, {1} bytes", arc.data.Count, fs.Length);
}
}
}
[Serializable, ProtoContract(Name = @"Archive"), ProtoInclude(1, typeof(List<ArchiveData>))]
public partial class Archive : IExtensible
{
[ProtoMember(1, IsRequired = true, OverwriteList = true, Name = @"data", DataFormat = DataFormat.Default)]
public List<ArchiveData> data { get; set; }
public Archive()
{
data = new List<ArchiveData>();
}
private IExtension extensionObject;
IExtension IExtensible.GetExtensionObject(bool createIfMissing)
{
return Extensible.GetExtensionObject(ref extensionObject, createIfMissing);
}
}
[ProtoContract]
public struct ArchiveData
{
[ProtoMember(1, IsRequired = false, OverwriteList = true, Name = @"sourcefolder", DataFormat = DataFormat.Default)]
[global::System.ComponentModel.DefaultValue("")]
public string sourcefolder { get; set; }
[ProtoMember(2, IsRequired = false, OverwriteList = true, Name = @"destinationfolder", DataFormat = DataFormat.Default)]
[global::System.ComponentModel.DefaultValue("")]
public string destinationfolder { get; set; }
[ProtoMember(3, IsRequired = false, OverwriteList = true, Name = @"period", DataFormat = DataFormat.FixedSize)]
[global::System.ComponentModel.DefaultValue((int)0)]
public int period { get; set; }
public ArchiveData(string sfolder = "", string dfolder = "", int priod = 0)
{
sourcefolder = sfolder;
destinationfolder = dfolder;
period = priod;
}
}