Nous avons un produit qui utilise 'XmlTextWriter' en C# - .NET 2.0 pour créer un grand nombre de petits fichiers XML. Ces fichiers sont ensuite lus à plusieurs reprises en utilisant 'XmlTextReader'.Les fichiers XML qui sont sérialisés à l'aide de XmlTextWriter puis lus à l'aide de XmlTextReader sont parfois corrompus
Nous avons constaté que, dans de très rares cas, sur quelques machines client, le contenu du fichier XML est remplacé par un grand nombre d'espaces blancs. Une fois que cela se produit, 'XmlTextReader' échouera évidemment à lire le fichier XML avec l'erreur "Root Element is missing".
Voici les détails logiques:
Lors de l'écriture d'un nouveau fichier Xml - le fichier est d'abord écrit dans un dossier temporaire à l'aide:
XmlTextWriter xDoc = new XmlTextWriter(Path, Encoding.UTF8);
Une fois que le fichier est écrit à la dossier temporaire - 'XmlTextReader' est utilisé pour vérifier le fichier.
Si et seulement si le fichier est vérifié, il est copié à l'emplacement final.
En quelques jours, le fichier est lu plusieurs fois à l'aide:
XmlTextReader xDoc = new XmlTextReader(Path);
Dans certains rares cas, le lecteur ne parvient avec l'erreur « élément racine est manquant » et nous voyons que le fichier XML contient maintenant un certain nombre d'espaces et pas de données XML.
Voici quelques extraits de code:
Ce code est utilisé pour la sérialisation.
(Gardez à l'esprit que la sérialisation est fait dans un dossier temporaire et seulement copié sur l'emplacement final une fois que le xmlFile temporaire est vérifiée.)
public void SerializeWithXmlTextWriter(XMLMetaData instance, string Path)
{
instance.CommitLists();
#region XmlTextWriter
XmlTextWriter xDoc = null;
try
{
xDoc = new XmlTextWriter(Path, Encoding.UTF8);
xDoc.Formatting = Formatting.Indented;
xDoc.WriteProcessingInstruction("xml", "version=\"1.0\" encoding=\"utf-8\"");
xDoc.WriteStartElement("MD");
xDoc.WriteAttributeString("xmlns", "xsi", null, "http://www.w3.org/2001/XMLSchema-instance");
xDoc.WriteAttributeString("xmlns", "xsd", null, "http://www.w3.org/2001/XMLSchema");
// A number of other elements are written here
xDoc.WriteEndElement();
}
finally
{
if (xDoc != null)
{
xDoc.Close();
xDoc = null;
}
}
#endregion
}
Ce code est utilisé pour la désérialisation.
(il est également utilisé pour vérifier le fichier après sérialisation.)
public XMLMetaData DeserializeWithXmlTextReader(string Path)
{
XMLMetaData instance = new XMLMetaData();
#region XmlTextReader
XmlTextReader xDoc = null;
try
{
xDoc = new XmlTextReader(Path);
while (xDoc.Read())
{
switch (xDoc.Name)
{
//Each element is processed using a case statement
//Omitted from this code sample
}
}
}
finally
{
if (xDoc != null)
{
xDoc.Close();
xDoc = null;
}
}
#endregion
return instance;
}
Nous avons essayé de résoudre ce problème pour un certain nombre de mois et ne peut aller nulle part, car il ne se produit que sur quelques machines clientes sur de milliers. Nous n'avons jamais été capables de le reproduire sur nos machines de développement et de test.
Nous avons eu des rapports indiquant que le problème disparaissait lorsque les applications de sauvegarde étaient arrêtées. Nous avons également un client qui semble seulement avoir des problèmes lors de l'exécution de Visual Studio.
Aussi pour les clients ayant ce problème - il semble que cela n'arrive que toutes les quelques semaines!
Merci d'avance pour votre aide :)
Simon
Comme vous pouvez remarquer que je n'appelle pas Flush() avant de fermer() XmlTextWriter. Si vous regardez des exemples sur MSDN - il semble qu'il n'y a pas besoin d'appeler Flush(). [link] (http://msdn.microsoft.com/fr-fr/library/system.xml.xmltextwriter.aspx) – Xmun
ne supposez pas que les exemples de code MSDN affichent les meilleures pratiques, voire fonctionnent. J'ai passé du temps à déboguer du code qui a été copié-collé à partir de MSDN avant. –
@Peter - Oui, je suis entièrement d'accord avec vous. Si vous regardez ce lien [link] (http://msdn.microsoft.com/fr-fr/library/system.xml.xmltextwriter.flush.aspx), il semble que Flush() n'est nécessaire que si vous n'appelez pas Fermer(). Je vais essayer quelques tests en utilisant Flush(). Le fait est que le contenu du fichier est correct avant que la copie du fichier ait lieu.C'est plus tard que le contenu du fichier est corrompu! En outre, le code actuel échoue seulement pour une poignée de nos 5000+ utilisateurs. – Xmun