C# 使用Protobuf net反序列化二进制文件时,导线类型无效

C# 使用Protobuf net反序列化二进制文件时,导线类型无效,c#,deserialization,protobuf-net,C#,Deserialization,Protobuf Net,是什么导致了这个错误 Invalid wire-type; this usually means you have over-written a file without truncating or setting the length; see http://stackoverflow.com/q/2152978/23354 我按照上面的帮助链接,但是设置FileMode.Truncate没有帮助 问题总是发生在反序列化的特定文件中的同一位置。我已多次重新创建该文件 [ProtoCont

是什么导致了这个错误

Invalid wire-type; this usually means you have over-written a file without truncating or setting the length; see http://stackoverflow.com/q/2152978/23354
我按照上面的帮助链接,但是设置FileMode.Truncate没有帮助

问题总是发生在反序列化的特定文件中的同一位置。我已多次重新创建该文件

  [ProtoContract]
    public class TickRecord
    {
        [ProtoMember(1, DataFormat = DataFormat.FixedSize)]
        public DateTime DT;
        [ProtoMember(2)]
        public double BidPrice;
        [ProtoMember(3)]
        public double AskPrice;
        [ProtoMember(4, DataFormat = DataFormat.FixedSize)]
        public int BidSize;
        [ProtoMember(5, DataFormat = DataFormat.FixedSize)]
        public int AskSize;

        public TickRecord(DateTime DT, double BidPrice, double AskPrice, int BidSize, int AskSize)
        {
            this.DT = DT;
            this.BidPrice = BidPrice;
            this.AskPrice = AskPrice;
            this.BidSize = BidSize;
            this.AskSize = AskSize;

        }

        public TickRecord()
        {
        }
}
为JON SKEET编辑

这很有效。但当我使用真实数据(我无法共享)时,我的问题就出现了。我反序列化的大多数文件都可以正常工作,但有一个文件不能

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using ProtoBuf;
using System.IO;
using System.Diagnostics;

namespace BinTest3
{


    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void Serialize_Click(object sender, EventArgs e)
        {

            FileStream outBin = null;

            string binFileName = @"C:\binfile.dft";
            outBin = File.Create(binFileName, 2048, FileOptions.None);

            DateTime d = DateTime.Now;

            TickRecord tr = new TickRecord(d, 1.02, 1.03,200,300);

            for (int i =0; i < 20000000; i++)
            {
                tr.BidPrice += 1;
                Serializer.SerializeWithLengthPrefix(outBin, tr, PrefixStyle.Base128);
            }

            outBin.Close();
            label1.Text = "Done ";
        }

        private void Deserialize_Click(object sender, EventArgs e)
        {
            Stopwatch sw = new Stopwatch();
            sw.Start();

            FileStream fs;
            string binFileName = @"C:\binfile.dft";

            byte[] data = File.ReadAllBytes(binFileName);
            MemoryStream ms = new MemoryStream(data);

            long skipRate =10;
            int count = 0;
            TickRecord tr;

            long skip = (38*skipRate);
            try
            {

                while ((tr = Serializer.DeserializeWithLengthPrefix<TickRecord>(ms, PrefixStyle.Base128)) != null) //fs.Length > fs.Position)
                {
                    count++;


                    ms.Seek(skip, SeekOrigin.Current);

                }
            }
            catch (Exception)
            {

            }

            ms.Close();

            sw.Stop();
            label1.Text = "Time taken: " + sw.Elapsed + " Count: " + count.ToString("n0");

        }
    }


    [ProtoContract]
    public class TickRecord
    {

        [ProtoMember(1, DataFormat = DataFormat.FixedSize)]
        public DateTime DT;
        [ProtoMember(2)]
        public double BidPrice;
        [ProtoMember(3)]
        public double AskPrice;
        [ProtoMember(4, DataFormat = DataFormat.FixedSize)]
        public int BidSize;
        [ProtoMember(5, DataFormat = DataFormat.FixedSize)]
        public int AskSize;

        public TickRecord()
        {

        }

        public TickRecord(DateTime DT, double BidPrice, double AskPrice, int BidSize, int AskSize)
        {
            this.DT = DT;
            this.BidPrice = BidPrice;
            this.AskPrice = AskPrice;
            this.BidSize = BidSize;
            this.AskSize = AskSize;

        }



    }
}
[原始合同] 公开课记录 {

}

这使得:

outBin.Position: 38 lastPosition: 0 diff: 38
outBin.Position: 67 lastPosition: 38 diff: 29
因此,当变量为零时,它的大小似乎不同


如何使零双精度的大小与非零双精度的大小相同?

您需要IsRequired属性

零值double和int字段的序列化方式与非零字段不同。因此,尽管我指定了FixedSize,但事实并非如此

下面创建了一个真正固定大小的记录:

 [ProtoContract]
    public class TickRecord
    {
        [ProtoMember(1, DataFormat = DataFormat.FixedSize, IsRequired = true)]
        public DateTime DT;
        [ProtoMember(2, DataFormat = DataFormat.FixedSize, IsRequired = true)]
        public double BidPrice;
        [ProtoMember(3, DataFormat = DataFormat.FixedSize, IsRequired = true)]
        public double AskPrice;
        [ProtoMember(4, DataFormat = DataFormat.FixedSize, IsRequired = true)]
        public int BidSize;
        [ProtoMember(5, DataFormat = DataFormat.FixedSize, IsRequired = true)]
        public int AskSize;

你能展示一个简短但完整的程序来演示这个问题吗?考虑到之前你在溪流中跳跃,我想知道你是否跳错了地方…@JonSkeet这里是一个SSCCE。它没有显示实际错误,因为我无法上传大数据文件。如果您愿意-我可以直接通过电子邮件发送给您…您确定严格要求指定
DataFormat=DataFormat.FixedSize
?我相信反序列化程序可以自己找到整数的大小。在我看来,这只会带来麻烦。@aevitas:这是为了确保它是一个固定大小的整数,而不是一个可变长度的整数。这里的背景是OP真的想要一个固定的记录长度。你有多确定38是正确的数字?你能用少于2000万条记录重现这个问题吗?它总是在同一个数字上失败吗?如果你以这个出价开始,它会立即失败吗?稍后将尝试您的代码(现在不能这样做),但您可以将其锁定得越多越好。
outBin.Position: 38 lastPosition: 0 diff: 38
outBin.Position: 67 lastPosition: 38 diff: 29
 [ProtoContract]
    public class TickRecord
    {
        [ProtoMember(1, DataFormat = DataFormat.FixedSize, IsRequired = true)]
        public DateTime DT;
        [ProtoMember(2, DataFormat = DataFormat.FixedSize, IsRequired = true)]
        public double BidPrice;
        [ProtoMember(3, DataFormat = DataFormat.FixedSize, IsRequired = true)]
        public double AskPrice;
        [ProtoMember(4, DataFormat = DataFormat.FixedSize, IsRequired = true)]
        public int BidSize;
        [ProtoMember(5, DataFormat = DataFormat.FixedSize, IsRequired = true)]
        public int AskSize;