【发布时间】:2021-02-17 02:43:37
【问题描述】:
我有一个程序会检查数千个文件,并且必须检查它们是否具有正确的 xml 格式。 问题是它需要很长时间才能完成,我认为这是因为我使用的 xml 阅读器的类型。
在下面的方法中,我尝试了 3 个不同的版本,第一个是最快的,但只有 5%。 (该方法不需要检查文件是否为xml)
private bool HasCorrectXmlFormat(string filePath)
{
try
{
//-Version 1----------------------------------------------------------------------------------------
XmlReader reader = XmlReader.Create(filePath, new XmlReaderSettings() { IgnoreComments = true, IgnoreWhitespace = true });
string[] elementNames = new string[] { "DocumentElement", "Protocol", "DateTime", "Item", "Value" };
int i = 0;
while (reader.Read())
{
if (reader.NodeType == XmlNodeType.Element)
{
if (reader.Name != elementNames.ElementAt(i))
{
return false;
}
if (i >= 4)
{
return true;
}
i++;
}
}
return false;
//--------------------------------------------------------------------------------------------------
//- Version 2 ------------------------------------------------------------------------------------
IEnumerable<XElement> xmlElements = XDocument.Load(filePath).Descendants();
string[] elementNames = new string[] { "DocumentElement", "Protocol", "DateTime", "Item", "Value" };
for (int i = 0; i < 5; i++)
{
if (xmlElements.ElementAt(i).Name != elementNames.ElementAt(i))
{
return false;
}
}
return true;
//--------------------------------------------------------------------------------------------------
//- Version 3 ------------------------------------------------------------------------------------
XDocument doc = XDocument.Load(filePath);
if (doc.Root.Name != "DocumentElement")
{
return false;
}
if (doc.Root.Elements().First().Name != "Protocol")
{
return false;
}
if (doc.Root.Elements().First().Elements().ElementAt(0).Name != "DateTime")
{
return false;
}
if (doc.Root.Elements().First().Elements().ElementAt(1).Name != "Item")
{
return false;
}
if (doc.Root.Elements().First().Elements().ElementAt(2).Name != "Value")
{
return false;
}
return true;
//--------------------------------------------------------------------------------------------------
}
catch (Exception)
{
return false;
}
}
我需要的是一种更快的方法来做到这一点。有没有更快的方法来浏览 xml 文件?我只需要检查前 5 个元素的名称是否正确。
更新
Xml 文件的大小只有 2-5 KB,很少超过这个大小。文件位于本地服务器上。我在一台有固态硬盘的笔记本电脑上。
以下是一些测试结果:
我还应该补充一点,文件是之前过滤的,所以只有 xml 文件被赋予该方法。我使用以下方法获取文件:
public List<FileInfo> GetCompatibleFiles()
{
return new DirectoryInfo(folderPath)
.EnumerateFiles("*", searchOption)
.AsParallel()
.Where(file => file.Extension == ".xml" ? HasCorrectXmlFormat(file.FullName) : false)
.ToList();
}
我的代码中没有这个方法(它把两个方法放在一起),这只是为了说明如何调用 HasCorrectXmlFormat 方法。这个方法不用改,我知道是可以改进的。
UDPATE 2
这里是更新 1 末尾提到的两个完整方法:
private void WriteAllFilesInList()
{
allFiles = new DirectoryInfo(folderPath)
.EnumerateFiles("*", searchOption)
.AsParallel()
.ToList();
}
private void WriteCompatibleFilesInList()
{
compatibleFiles = allFiles
.Where(file => file.Extension == ".xml" ? HasCorrectXmlFormat(file.FullName) : false)
.ToList();
}
这两个方法在整个程序中只调用一次(如果allFiles 或compatibleFiles 列表为空)。
更新 3
WriteAllFilesInList 方法似乎是这里的真正问题,如下所示:
最终更新
看起来,我的方法不需要任何改进,因为瓶颈是别的东西。
【问题讨论】:
-
编写一个模式文件来进行您需要的验证并使用预制的模式验证器?
-
你不会轻易得到比 XmlReader 更快的东西。您是否检查过处理时间是由 I/O 还是由 CPU 决定的?在后一种情况下,您可能会尝试并行检查多个文件。
-
@jdweng OP 在哪里使用 XML 序列化?
-
你确认外循环是正确的吗?也许你做的工作比你想象的要多?例如。多次读取同一个文件
-
您能分享一下版本 1、版本 2 和版本 3 的性能测量结果吗?此外,您正在验证的 XML 文件的平均大小是多少,您使用的硬件存储类型是什么(硬盘驱动器?SSD?),它位于哪里(本地机器、本地网络等)?
标签: c# xml performance xmlreader