【问题标题】:Parsing 80 Gb XML File in c#在 C# 中解析 80 Gb XML 文件
【发布时间】:2016-08-25 19:35:08
【问题描述】:

我必须解析 80 GB 的 XML 才能从该文件中获取一些数据。为此,我使用了 XML 阅读器。当我使用 304 MB 文件检查代码时。然后它在 4 秒内解析文件。所以我想我会为 80 GB 工作。但它在几分钟后给了我异常的记忆。

我有以下代码:

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


        }
    }
}
}

所以请建议。感谢您的帮助。

【问题讨论】:

标签: c#


【解决方案1】:

你是对的,XmlReader 是正确的方法。而且,内存不足的不是XmlReader,而是您的lstTest,您将找到的大多数节点推到了那里。

使用XmlReader 的正确方法是处理节点,然后忘记它们,继续前进。您可以将结果写入磁盘,或计算一些运行总数,或其他任何东西 - 但不要将读取的所有内容都保存在内存中 - 这违背了XmlReader 的目的。

【讨论】:

    【解决方案2】:

    您不应该将所有内容都存储到内存中,而只保留您感兴趣的部分。

    这可以通过IEnumerable&lt;&gt; 和yield return 关键字来完成:

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

    用法:

    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
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-07-15
      • 2013-09-02
      • 2018-11-26
      • 2014-12-06
      • 1970-01-01
      • 1970-01-01
      • 2012-01-01
      • 2023-04-07
      相关资源
      最近更新 更多