2

The machine power was cut while, I assume, my application was updating a file. When turned back on and my application started it attempted to deserialize the file. The call to Serializer.Deserialize did not fail, but the resulting object has default values for every property.

My file updating/saving:

using (FileStream theStream = File.Open(fileName + "_tmp", FileMode.Create)) {
    ProtoBuf.Serializer.Serialize<MyObject>(theStream, inObjectToSerialize);
}
File.Copy(fileName + "_tmp", fileName, true);

There is no _tmp file, just the main file. The size of the file is non-zero which makes me believe the information is intact. Is there a way to recover this data?

Update:

I've tried the Marc's suggestion with ProtoReader and the file in questions causes an exception the be thrown at reader.ReadFieldHeader(). The ProtoException reads: "Invalid field in source data:0"

Dan Vogel
  • 3,858
  • 7
  • 41
  • 57
  • 1
    Is that (edit) right away? Or if not: how far through? If near the end, you can use the constructor to limit how much is read. How big is the file? If you are able to share the file, I may be able to use knowledge of the format to recover more than "until it went bang", bit I can't make promises. – Marc Gravell Oct 02 '12 at 18:39
  • @MarcGravell It happens right away. I'll put together a sample project so you can see what I'm working with. – Dan Vogel Oct 02 '12 at 21:37

1 Answers1

3

There isn't much for me to go on there... I guess the short version would be: it depends what is left in the file.

One thing you could do would be to walk the file to see what is there:

using (var input = File.OpenRead(path))
using (var reader = new ProtoReader(input, RuntimeTypeModel.Default, null))
{
    while (reader.ReadFieldHeader() > 0)
    {
        Console.WriteLine("offset {0}, field {1}, type {2}",
            reader.Position, reader.FieldNumber, reader.WireType);
        reader.SkipField();
    }
}

That would at least allow you to see how much data is currently processing.

If you know the layout of some fields (i.e. "field 3 is a string, field 7 is a sub-object, etc"), then you could make the output more detailed.

Marc Gravell
  • 1,026,079
  • 266
  • 2,566
  • 2,900
  • I've attempted your suggestion, but found out that I have been using r282. It seems its been awhile since I've run into protobuf-net issues. So I downloaded r580 and tried dropping it in. Now when I try to deserialize previously successful files I get "NotSupportedException:IExtensible is not supported in structs or classes with inheritance" and with a different serialized object I get "InvalidOperationException: No serializer defined for type: System.Net.IP.Address". Now I'm worse off than I was. – Dan Vogel Oct 01 '12 at 22:20
  • @DanVogel `IPAddress` can be enable via `var model = TypeModel.Create();model.AllowParseableTypes = true;` and using `model.Serialize(...)` etc instead of `Serializer.Serialize`. The `IExtensible` warning was added to address an issue that may also impact r282 - I could probably do something to let that get past. However! All of these points are moot: the first thing to assess here is the state of the file, and just using `ProtoReader` by itself won't raise the issues you've described. – Marc Gravell Oct 02 '12 at 11:36
  • True. I guess I got ahead of myself. I've run your suggestion with regard to ProtoReader and updated my original post. – Dan Vogel Oct 02 '12 at 16:31