2016-12-04 23 views
1

ノードを既存のXMLファイルから新しく作成したXMLファイルにコピーする必要があります。 私はXDocumentインスタンスを使用して既存のXMLファイルにアクセスしています。問題は、XMLファイルがかなり大きくなりうることです(500K行、Openstreetmapデータなど)。XDocumentを使用して大規模なXMLファイルをループする

メモリエラーを発生させずに大きなXMLファイルをループするにはどうすればよいでしょうか?

私は現在XDocument.Load(path)を使用し、doc.Descendants()でループしますが、ループが完了するまでプログラムがフリーズします。だから私は非同期にループする必要があると思うが、私はこれを達成するための最良の方法を知らない。

+2

'XmlReader'と' IEnumerable'イテレータ( 'yield') – Fabio

答えて

5

イテレータXmlReaderIEnumerable<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 ; 
       } 
      } 
     } 
    } 
} 

あなたは非同期に続いて

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; 
} 

することができますループのすべてのファイルを非同期ファイルを読み込み、結果を待つことができ

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; 
関連する問題