2

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?

Arzu Suleymanov
  • 671
  • 2
  • 11
  • 33
ManInMoon
  • 6,795
  • 15
  • 70
  • 133
  • Can you show a short but *complete* program demonstrating the problem? Given that previously you were skipping around the stream, I wonder whether you've skipped to the wrong place... – Jon Skeet Apr 07 '14 at 11:52
  • @JonSkeet Here is an SSCCE. It does not show the actual error because I can't upload big data file. If you would like - I could email that to you direct... – ManInMoon Apr 07 '14 at 12:06
  • Are you sure specifying `DataFormat = DataFormat.FixedSize` is strictly required? I'm fairly confident the deserializer can find the size of an integer by itself. To me that looks like it could only cause trouble. – aevitas Apr 07 '14 at 12:33
  • 1
    @aevitas: That's to ensure that it's a fixed-size integer rather than a variable-length one. The background here is that the OP really wants a fixed record length. – Jon Skeet Apr 07 '14 at 13:01
  • How certain are you that 38 is the right number here? Can you reproduce the problem with fewer than 20 million records? Does it always fail at the same number, and if you start it with that bid price, does it fail immediately? Will try your code later (can't do so right now) but the more you can pin it down, the better. – Jon Skeet Apr 07 '14 at 13:02
  • @JonSkeet I have identified the problem. See EDIT 2 above please. Any ideas how to fix? – ManInMoon Apr 07 '14 at 13:10

1 Answers1

3

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;
ManInMoon
  • 6,795
  • 15
  • 70
  • 133