我必须将现有XML文件中的节点复制到新创建的XML文件中.我正在使用XDocument实例来访问现有的XML文件.问题是XML文件可能非常大(比方说500K行; Openstreetmap数据).
在不引起内存错误的情况下循环遍历大型XML文件的最佳方法是什么?
我目前只是使用XDocument.Load(path)和循环doc.Descendants(),但这会导致程序冻结,直到循环完成.所以我认为我必须循环异步,但我不知道实现这一目标的最佳方法.
您可以使用XmlReader和IEnumerable<XElement>迭代器来生成所需的元素.
这种方法不是异步的,但它可以节省内存,因为您不需要在内存中加载整个文件进行处理.只有您选择要复制的元素.
public IEnumerable<XElement> ReadFile(string pathToTheFile)
{
using (XmlReader reader = XmlReader.Create(pathToTheFile))
{
reader.MoveToContent();
while (reader.Read())
{
If (reader.NodeType == XmlNodeType.Element)
{
if (reader.Name.Equals("yourElementName"))
{
XElement element = XElement.ReadFrom(reader) as XElement;
yield return element ;
}
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
您可以异步读取文件
public async Task<IEnumerable<XElement>> ReadFileAsync(string pathToTheFile)
{
var elements = new List<XElement>();
var xmlSettings = new XmlReaderSettings { Async = true };
using (XmlReader reader = XmlReader.Create(pathToTheFile, xmlSettings))
{
await reader.MoveToContentAsync();
while (await reader.ReadAsync())
{
If (reader.NodeType == XmlNodeType.Element)
{
if (reader.Name.Equals("yourElementName"))
{
XElement element = XElement.ReadFrom(reader) as XElement;
elements.Add(element);
}
}
}
}
return elements;
}
Run Code Online (Sandbox Code Playgroud)
然后,您可以异步循环所有文件并等待结果
var fileTask1 = ReadFileAsync(filePath1);
var fileTask2 = ReadFileAsync(filePath2);
var fileTask3 = ReadFileAsync(filePath3);
await Task.WhenAll(new Task[] { fileTask1, fileTask2, fileTask3} );
// use results
var elementsFromFile1 = fileTask1.Result;
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
763 次 |
| 最近记录: |