2016-08-25 4 views
1

そのファイルからデータを取得するには、80GBのXMLを解析する必要があります。私はこの目的のためにXMLリーダーを使用しました。私は304 MBファイルでコードをチェックした。次に、4秒以内にファイルを解析します。だから私は80GBのために働くと思った。しかし、それは私に数分後に例外的なメモリを与えています。Cでの80Gb XMLファイルの解析#

私は、次のコードがありますので、お勧めしてください

static void Main(string[] args) 
    { 

     List<Test> lstTest = new List<Test>(); 
     bool isTitle = false; 
     bool isText = false; 

     using (XmlReader Reader = XmlReader.Create(FilePath)) 
     { 
      Test tt = new Test(); 
      while (Reader.Read()) 
      {     switch (Reader.NodeType) 
       { 
        case XmlNodeType.Element: 
         if (Reader.Name == "title") 
         { 
          isTitle = true; 
         } 
         if (Reader.Name == "text") 
         { 
          isText = true; 
         } 
         break; 
        case XmlNodeType.Text: 
         if (isTitle) 
         { 
          tt.Title = Reader.Value; 
          isTitle = false; 
         } 

         if (isText) 
         { 
          tt.Text = Reader.Value; 
          isText = false; 
         } 
         break; 
       } 

       if (tt.Text != null) 
       { 
        lstTest.Add(tt); 
        tt = new Test(); 
       } 
      } 


     } 
    } 
} 
} 

を。ご協力いただきありがとうございます。

+0

あなたは、各繰り返して行くと、あなたは 'lstTest'オブジェクトのサイズを確認することができます。私は間違っているかもしれないが、私は 'lstTest'が大きすぎてメモリが足りなくなっていると思う。 –

+4

http://stackoverflow.com/questions/15772031/how-to-parse-very-huge-xml-files-in-c – VDWWD

答えて

5

あなたは正しいです、XmlReaderは正しい方法です。また、メモリが不足しているのはXmlReaderではありません。あなたが見つけたほとんどのノードを移動するのはlstTestです。

XmlReaderを使用する正しい方法は、ノードを処理してから忘れることです。結果をディスクに書き込んだり、いくつかの実行中の合計を計算したり、メモリ内に読み込んだものすべてを保持しないで、XmlReaderの目的を破ることができます。

3

あなたはメモリにすべてを保存するのではなく、興味のある部分だけを保存してください。

public IEnumerable<Test> ParseXml(string path) 
{ 
    bool isTitle = false; 
    bool isText = false; 

    using (XmlReader Reader = XmlReader.Create(FilePath)) 
    { 
     Test tt = new Test(); 
     while (Reader.Read()) 
     {      
      switch (Reader.NodeType) 
      { 
       case XmlNodeType.Element: 
        if (Reader.Name == "title") 
        { 
         isTitle = true; 
        } 
        if (Reader.Name == "text") 
        { 
         isText = true; 
        } 
        break; 

       case XmlNodeType.Text: 
        if (isTitle) 
        { 
         tt.Title = Reader.Value; 
         isTitle = false; 
        } 

        if (isText) 
        { 
         tt.Text = Reader.Value; 
         isText = false; 
        } 
        break; 
      } 

      if (tt.Text != null) 
      { 
       yield return tt; 
       tt = new Test(); 
      } 
     } 
    } 
} 

使用法:

これはIEnumerable<>yield returnキーワードを介して行うことができます

var data = ParseXml(/* your xml file */); 

// select the part that you are interested in 
var interestingTests = data 
    .Where(x => x.Title == "...") 

foreach (var test in interestingTests) 
{ 
    // work with the interesting parts 
}