ManInMoon
ManInMoon

Reputation: 7005

Invalid wire-type when deserializing a binary file with Protobuf-net

What might be causing this error?

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

I followed the help link above, but setting FileMode.Truncate has not helped...

The issue always happen at same position in one particular file being deserialized. I have recreated the file several times.

    [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()
        {
        }
}

EDIT FOR JON SKEET

This works. But my problem arises when I use my real data (which I cannot share). Most file I deserialize work fine, but one does not....

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;

        }



    }
}

EDIT 2 PROBLEM IS IN Serialize - it is NOT fixedsize as I had thought:

private void Once_Click(object sender, EventArgs e)
{
    FileStream outBin = null;

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

    DateTime d = DateTime.Now;
    long lastPosition = 0;

    TickRecord tr = new TickRecord(d, 1.02, 1.03, 200, 300);
    Serializer.SerializeWithLengthPrefix(outBin, tr, PrefixStyle.Base128);
    Console.WriteLine("outBin.Position: " + outBin.Position + " lastPosition: " + lastPosition + " diff: " + (outBin.Position-lastPosition));
    lastPosition = outBin.Position;
    tr = new TickRecord(d, 1.02, 0.0, 200, 300);
    Serializer.SerializeWithLengthPrefix(outBin, tr, PrefixStyle.Base128);
    Console.WriteLine("outBin.Position: " + outBin.Position + " lastPosition: " + lastPosition + " diff: " + (outBin.Position - lastPosition));


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

}



  [ProtoContract]
  public class TickRecord
  {

    [ProtoMember(1, DataFormat = DataFormat.FixedSize)]
    public DateTime DT;
    [ProtoMember(2, DataFormat = DataFormat.FixedSize)]
    public double BidPrice;
    [ProtoMember(3, DataFormat = DataFormat.FixedSize)]
    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;

}



}

This gives:

outBin.Position: 38 lastPosition: 0 diff: 38
outBin.Position: 67 lastPosition: 38 diff: 29

So it appears that the size of the variable is different when it is ZERO.

How can I make a ZERO double get same size as a non-zero double?

Upvotes: 2

Views: 10259

Answers (1)

ManInMoon
ManInMoon

Reputation: 7005

You need IsRequired attribute.

ZERO-valued double and int fields are serialized differently to non-zero fields. So although I specified FixedSize - it was not.

The following creates a really FixedSize record:

 [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;

Upvotes: 3

Related Questions