【发布时间】:2017-03-28 22:18:04
【问题描述】:
我想序列化List<ArchiveData>,但它几乎总是失败。 Protobuff 抛出以下异常:
线型无效;这通常意味着您已经覆盖了一个文件 不截断或设置长度;看 Using Protobuf-net, I suddenly got an exception about an unknown wire-type
我已经阅读了帖子,但仍然找不到解决方案。如何序列化和反序列化?
我的类和结构:
[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;
}
}
我使用以下方法对其进行序列化:
public static void Refresh(ref Archive arc)
{
if (File.Exists(probuffile))
{
using (var fs = File.OpenRead(probuffile))
{
arc = Serializer.Deserialize<Archive>(fs);
}
}
}
我用以下方法反序列化:
public static void Update(Archive arc)
{
using (var fs = File.Create(probuffile))
{
Serializer.Serialize<Archive>(fs, arc);
fs.SetLength(fs.Position);
}
}
我使用它:
Archive archive = new Archive();
//Add some ArchiveData.
Refresh(ref archive);
------------------编辑---- --------------
已添加此部分以获取更多信息。当我像下面的代码一样使用 SerializeWithLengthPrefix / DeserializeWithLengthPrefix 函数时,每次我使用 Deserialize 函数的第一个类都可以正常工作。但它为我使用反序列化函数的第二个类返回 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);
}
}
}
【问题讨论】:
-
我在问题中看不到任何
List<object>- 我可以假设这里的真正问题实际上只是“(反)序列化一个对象,我得到了线型错误”? -
对不起。我的错。我忘记写课了。
-
重新编辑:它们在同一个文件中吗?或不同的文件?如果您想从同一个文件中连续读取两个内容,则需要在单个
File.OpenRead会话中连续读取它们。否则,每次调用File.OpenRead时,它都会回到文件的开头并读取错误的数据。你没有展示如何使用Update和Refresh,所以我不能100% 确定。同样,最好的办法 - 就像在我的回答中一样 - 是发布一些 完全可运行 代码(使用Main()方法等)来演示实际发生的问题。 -
我放弃尝试序列化/反序列化两个不同的类。我将所有内容合二为一,并且工作正常。如果文件大小增加时速度变慢,我会尝试将类分成两个不同的类。感谢您的回答:)
标签: c# serialization protocol-buffers protobuf-net