2012-10-01 78 views
2

當我假設我的應用程序正在更新文件時,機器電源被切斷。當重新打開並且我的應用程序啓動時,它試圖反序列化文件。對Serializer.Deserialize的調用沒有失敗,但結果對象具有每個屬性的默認值。使用Protobuf-net恢復損壞的文件序列化

我的文件更新/保存:

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

沒有_TMP文件,只要主文件。該文件的大小非零,這使我相信信息是完整的。有沒有辦法恢復這些數據?

更新:

我已經試過了馬克與ProtoReader建議和問題的文件導致異常的reader.ReadFieldHeader()的拋出。 ProtoException讀道:「源數據中的無效字段:0」

+1

是(編輯)馬上?或者如果不是:通過多遠?如果接近尾聲,可以使用構造函數限制讀取的數量。文件有多大?如果你能夠共享文件,我可能會使用格式知識來恢復更多的「直到它爆炸」,我無法承諾。 –

+0

@MarcGravell它馬上就會發生。我將彙集一個示例項目,以便您可以看到我正在處理的事情。 –

回答

2

我沒有太多的去那裏......我猜短版將是:它取決於文件中剩下的內容。

有一件事你能做的只是走文件,看看還有什麼:

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(); 
    } 
} 

這將至少讓你看到目前有多少數據處理。

如果您知道某些字段的佈局(即「字段3是字符串,字段7是子對象等)」,則可以使輸出更加詳細。

+0

我試過你的建議,但發現我一直在使用r282。自從我遇到protobuf-net問題以來似乎已經有一段時間了。所以我下載了r580並嘗試將其放入。現在,當我嘗試反序列化先前成功的文件時,我得到「NotSupportedException:IExtensible在結構體或繼承類中不受支持」,並且具有不同的序列化對象「InvalidOperationException:No serializer defined for for鍵入:System.Net.IP.Address「。現在我比我更糟糕。 –

+0

@DanVogel'IPAddress'可以通過'var model = TypeModel.Create(); model.AllowParseableTypes = true;'使用'model.Serialize(...)'等來代替'Serializer.Serialize'啓用。 「IExtensible」警告是爲了解決可能影響r282的問題而添加的 - 我可能會採取一些措施讓這些問題得以解決。然而!所有這些觀點都是沒有意義的:首先要評估的是文件的狀態,而僅僅使用'ProtoReader'本身不會引發你描述的問題。 –

+0

是的。我想我已經超越了自己。我已經運行了關於ProtoReader的建議並更新了我的原始文章。 –