Reputation: 531
I have a file that n
instances of an object are serialized and stored in it.
In some cases I need to skip stored records and read in k 2k 3k ... n
sequence instead of normal 1 2 3 ... n
sequence. Since these instances don't have the same length I wrote this code to skip records, but it throws Invalid wire-type exception
. (and exception has a link to this question but it didn't help)
Is it just a simple mistake or I am doing this in a wrong way?
long position = stream.Position;
int length = 0;
for (int i = 0; i < skipRate; ++i)
{
Serializer.TryReadLengthPrefix(stream, PrefixStyle.Fixed32, out length);
position += length;
stream.Position = position;
Console.WriteLine("Skipped " + length + " bytes");
}
MYCLASS retval = Serializer.DeserializeWithLengthPrefix<MYCLASS>(stream, PrefixStyle.Fixed32, 1);
EDIT:
long position = stream.Position;
int length;
for (int i = 0; i < skipRate; ++i)
{
Serializer.TryReadLengthPrefix(stream, PrefixStyle.Fixed32, out length);
length += (int)(stream.Position - position); // add number of bytes that TryReadLengthPrefix moves stream
stream.Position = position; // Rewind
Serializer.DeserializeWithLengthPrefix<SimulationOutputData>(stream, PrefixStyle.Fixed32, 1);
Console.WriteLine("Try read returns " + length + ", but deserialize goes on " + (stream.Position-position));
}
Output:
Try read returns 1209, but deserialize goes on 1209
Try read returns 1186, but deserialize goes on 1186
Try read returns 1186, but deserialize goes on 1186
Try read returns 1186, but deserialize goes on 1186
Try read returns 1186, but deserialize goes on 1186
Try read returns 1209, but deserialize goes on 1209
Try read returns 1167, but deserialize goes on 1167
.
.
.
And this code works (WHY?!! what is the difference?):
Serializer.TryReadLengthPrefix(stream, PrefixStyle.Fixed32, out length);
length += (int)(stream.Position - position);
stream.Position = position;
position += length;
stream.Position = position;
Upvotes: 2
Views: 648
Reputation: 1064104
athabaska (comments) has the gist of it. Your position
increments aren't accounting for the headers. A neat implementation might be:
for (int i = 0; i < skipRate; ++i)
{
int length;
if(!Serializer.TryReadLengthPrefix(stream, PrefixStyle.Fixed32, out length))
{
throw new EndOfStreamException(); // not enough records
}
s.Seek(length, SeekOrigin.Current);
}
MYCLASS retval = Serializer.DeserializeWithLengthPrefix<MYCLASS>(
stream, PrefixStyle.Fixed32, 0);
Upvotes: 2