2017-10-13 2 views
0

J'utilise le code suivant pour stocker des objets sur le disque:DataContractSerializer écrit des données corrompues

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

Parfois, le fichier enregistré est corrompue, ce qui signifie qu'il se composent de certaines données des ordures supplémentaires au hasard qui empêche désérialisation plus, par exemple quelque chose comme ceci:

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

Voici les 6 derniers caractères proviennent de quelques restes de l'étiquette et éviter de désérialisation ce fichier. Pourquoi cela arrive-t-il et comment puis-je le réparer?

Peut-elle être provoquée en appelant la méthode Save dans le gestionnaire d'événements Form.Closing?

+1

Kinda semble écrire plusieurs fois dans le même fichier et le fichier n'est pas tronqué avant d'être réécrit. Si ce que vous avez écrit la dernière fois était six caractères plus long et s'est terminé avec "" comme le nouveau - vous êtes là. 'System.IO.File.Delete (filename);' comme la première ligne de la méthode devrait effacer cela, je pense. Je ne sais pas si cela se produit lorsque le fichier n'existe pas. –

+0

@EdPlunkett Bien sûr! à partir de la documentation d'OpenWrite: "Ouvre un fichier existant ou crée un nouveau fichier à écrire." Merci beaucoup! – Szybki

+3

Utilisez 'new System.IO.FileStream (filename, FileMode.Create)' à la place de 'OpenWrite'. –

Répondre

1

Ceci est documented behavior with OpenWrite():

La méthode OpenWrite ouvre un fichier si l'on existe déjà pour le chemin du fichier, ou crée un nouveau fichier si l'on n'existe pas. Pour un fichier existant, il n'ajoute pas le nouveau texte au texte existant. Au lieu de cela, il écrase les caractères existants avec les nouveaux caractères. Si vous remplacez une chaîne plus longue (comme "Ceci est un test de la méthode OpenWrite") avec une chaîne plus courte (comme "Deuxième exécution"), le fichier contiendra un mélange des chaînes (" Deuxième test de la méthode OpenWrite ").

Vous devez donc explicitement tronquer le fichier avant de l'écrire, ou simplement le supprimer s'il existe.

Alexander Petrov observe que new System.IO.FileStream(filename, FileMode.Create) est le remplacement correct pour OpenWrite() dans ce cas.