在c#中解析80 Gb XML文件

时间:2016-08-25 19:35:08

标签: c#

我必须解析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();
                }
            }


        }
    }
}
}

所以请建议。谢谢你的帮助。

2 个答案:

答案 0 :(得分:6)

你是对的,XmlReader是正确的方法。并且XmlReader不是内存不足 - 这是你lstTest,你可以在那里推送你找到的大多数节点。

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

答案 1 :(得分:3)

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

可以通过IEnumerable<>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
}