【发布时间】:2011-09-11 16:08:10
【问题描述】:
我们有一个产品,它在 C# - .NET 2.0 中使用“XmlTextWriter”来创建大量的小型 XML 文件。然后使用“XmlTextReader”重复读取这些文件。
我们发现,在极少数客户机器上,XML 文件的内容会被大量空格替换。一旦发生这种情况,“XmlTextReader”显然将无法读取 XML 文件,并出现错误“缺少根元素”。
这里是逻辑细节:
-
当写入一个新的 Xml 文件时 - 文件首先被写入一个临时文件夹,使用:
XmlTextWriter xDoc = new XmlTextWriter(Path, Encoding.UTF8); 将文件写入临时文件夹后 - 'XmlTextReader' 用于验证文件。
当且仅当文件经过验证时,才会将其复制到最终位置。
-
几天之内,该文件被多次读取:
XmlTextReader xDoc = new XmlTextReader(Path); 在极少数情况下,读取器失败并显示错误“缺少根元素”,我们看到 XML 文件现在包含许多空格且没有 XML 数据。
以下是一些代码摘录:
此代码用于序列化。
(请记住,序列化是在临时文件夹中完成的,并且只有在验证了临时 XmlFile 后才会复制到最终位置。)
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
}
此代码用于反序列化。
(也用于序列化后的文件校验)
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;
}
几个月来,我们一直在努力解决这个问题,但无法取得任何进展,因为它只发生在数千台客户端计算机上。我们从未能够在我们的开发和测试机器上复制它。
我们收到了关于备份应用程序停止时问题消失的报告。我们还有一位客户似乎只在运行 Visual Studio 时遇到问题。
也适用于有此问题的客户 - 似乎每隔几周才会发生一次!
提前感谢您的帮助:)
西蒙
【问题讨论】:
-
您可能会注意到,我在 Close() XmlTextWriter 之前没有调用 Flush()。如果您查看 MSDN 上的示例 - 似乎不需要调用 Flush()。 link
-
不要假设 MSDN 代码示例展示了最佳实践,甚至可以正常工作。我曾经花时间调试之前从 MSDN 复制粘贴的代码。
-
@Peter - 是的,我完全同意你的看法。如果您查看此链接link,似乎只有在您不调用 Close() 时才需要 Flush()。我将尝试使用 Flush() 进行一些测试。问题是在文件复制发生之前文件的内容是正确的。后来文件的内容被破坏了!此外,目前的代码仅对我们 5000 多个用户中的一小部分失败。
-
您永远不应该使用
new XmlTextReader()或new XmlTextWriter()。自 .NET 2.0 以来,这些已被弃用。请改用XmlReader.Create()和XmlWriter.Create()。 -
@John...希望该类在使用 VS 时无需我寻找它就表明它已被弃用。会为我节省很多浪费的时间!