2017-10-13 139 views
0

我用下面的代碼來存儲在磁盤上的一些對象:DataContractSerializer的寫入損壞的數據

public static void Save<T>(T obj, string filename) 
    { 
     using (var output = System.IO.File.OpenWrite(filename)) 
     using (var writer = new System.Xml.XmlTextWriter(output, System.Text.Encoding.UTF8) 
     { 
      Formatting = System.Xml.Formatting.Indented 
     }) 
     { 
      var serializer = new System.Runtime.Serialization.DataContractSerializer(typeof(T)); 
      serializer.WriteObject(writer, obj); 
     } 
    } 

有時保存的文件被損壞,這意味着它由防止進一步的反序列化一些隨機附加的垃圾數據,例如這樣的事情:

<Parameters xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.datacontract.org/2004/07/MyApp"> 
    ... 
</Parameters>eters> 

這裏最後6個字符來自一些遺蹟的標籤和反序列化,從這個文件阻止。爲什麼會發生,我該如何解決?

是否可以通過調用Form.Closing事件處理程序中的Save方法引起?

+1

有點看起來像你正在重複寫入同一個文件,並且在你再次寫入文件之前文件沒有被截斷。如果你上次寫給它的內容長了六個字符,並且以「'''」結尾,就像新的一樣 - 你就是這樣。 'System.IO.File.Delete(filename);'作爲方法的第一行應該清除,我想。不知道是否在文件不存在時拋出。 –

+0

@EdPlunkett當然!從OpenWrite的文檔:「打開一個現有的文件或創建一個新的文件寫入。」非常感謝你! – Szybki

+3

使用'new System.IO.FileStream(filename,FileMode.Create)'而不是'OpenWrite'。 –

回答

1

這是documented behavior with OpenWrite()

的OpenWrite方法打開一個文件,如果一個已經存在的文件路徑,或創建一個新的文件,如果一個不存在。對於現有文件,它不會將新文本附加到現有文本。相反,它會用新字符覆蓋現有字符。 如果您用較短的字符串(如「第二次運行」),覆蓋較長的字符串(例如「這是對OpenWrite方法的測試」),該文件將包含字符串(「 OpenWrite方法的第二次運行測試「)。

因此,您需要在寫入之前明確地截斷文件,或者如果存在,就刪除它。

亞歷山大·彼得羅夫指出new System.IO.FileStream(filename, FileMode.Create)OpenWrite()在這種情況下,正確的替換。