解析80gb的XML文件

本文关键字:文件 XML 80gb 解析 | 更新日期: 2023-09-27 18:04:15

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

        }
    }
}
}

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

解析80gb的XML文件

你是对的,XmlReader是正确的方法。这不是XmlReader内存耗尽-这是你的lstTest,你把你找到的大多数节点。

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

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

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