在多个 XML 文件中搜索字符串
本文关键字:搜索 字符串 文件 XML | 更新日期: 2023-09-27 18:33:33
我有一个文件夹,里面有400k+ XML文档,还有更多,每个文件都以"ID".xml命名,每个文件都属于一个特定的用户。在SQL服务器数据库中,我有XML文件中的"ID"与用户ID匹配,这是我将XML文档与用户互连的地方。用户可以附加无限数量的XML文档(但假设最多>10k个文档)
所有 XML 文档都有一些通用元素,但结构可能会略有不同。
现在,每个用户都需要在属于她的XML文档中进行搜索,而到目前为止我尝试过的(循环访问每个文件并使用流阅读器读取)太慢了。我不在乎,它是否读取并使用属性等匹配整个文件,或者只是每个元素中的文本。首先应该返回的是一个列表,其中包含文件名中的 ID。
如果有的话,这里最快、最聪明的方法是什么?
我认为LINQ-to-XML可能是你想要的方向。
假设您知道所需标签的名称,您将能够搜索这些特定元素并返回值。
var xDoc = XDocument.Load("yourFile.xml");
var result = from dec in xDoc.Descendants()
where dec.Name == "tagName"
select dec.Value;
然后,results
将包含具有与"tagName"匹配的名称的任何 XML 标记的值的IEnumerable
查询也可以这样编写:
var result = from dec in xDoc.Decendants("tagName")
select dec.Value;
或者这个:
var result = xDoc.Descendants("tagName").Select(tag => tag.Value);
输出将是相同的,只是根据元素名称进行过滤的不同方法。
你必须打开每个包含相关数据的文件,如果你不知道哪些文件包含它,你必须打开所有可能匹配的文件。因此,唯一的性能提升是在解析例程中。
解析 XML 时,如果需要速度,则可以使用该XmlReader
,因为它的性能比其他解析器更好(大多数解析器在查询它们之前会读取整个 Xml 文件)。它仅向前的事实不应成为这种情况的限制。
如果解析花费的时间与磁盘 I/O 一样长,则可以尝试并行解析文件,以便一个线程可以等待读取文件,而另一个线程可以分析加载的数据。不过,我不认为你能在那里取得那么大的胜利。
还有什么是"太慢",什么是可以接受的?这种包含许多文件的解决方案会随着时间的推移而变慢吗?
使用 LINQ to XML。
看看这篇文章。 在MSDN那边。
XDocument doc = XDocument.Load("C:'file.xml");
并且不要忘记读取这么多文件总是很慢,您可以尝试编写多线程程序......
理解正确,您不想为特定用户打开每个 xml 文件,因为无论您使用 linq to xml 还是其他方法,它都太慢了。您是否考虑过在 xml 文件和关系数据库(标记)中保存一些值(以及 xml ID)。在这种情况下,您可以先在数据库中搜索某些值,然后仅选择包含搜索值的 xml 文件?
例如:ID, 标签名称 1, 标签名称 2xmlDocID, 值 1, 值 2
我的另一个问题是,为什么选择将XML文档存储在文件系统中。如果您使用的是SQL Server 2005/2008,它对存储,搜索xml列(甚至为xml中的某些值编制索引)提供了很好的支持。
您是否只是在某处查找内容中具有特定字符串的文件?
警告 - 不是纯 .NET 解决方案。 如果这让你感到害怕,那就坚持其他答案。:)
如果这就是你正在做的事情,另一种选择是让像 grep 这样的东西为你做繁重的工作。 用"-l"参数来指定你只对文件名感兴趣,并且你是一个赢家。 (有关更多使用示例,请参阅此链接)
L.B 已经提出了一个有效的观点。在这种情况下,Lucene.Net(或任何索引器)是必须的。它会在所有搜索中为您提供稳定(非常快)的性能。这是索引器的主要优势之一,可以处理非常大量的任意数据。
或者有什么理由,为什么你不使用Lucene?
Lucene.NET(和Lucene)支持增量索引。如果可以每隔一段时间重新打开索引进行阅读,那么可以整天不断向索引中添加文档 - 您的搜索将与上次重新打开索引进行搜索时保持同步。