首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >ReadOuterXml正在抛出OutOfMemoryException读取大(1 GB) XML文件的一部分

ReadOuterXml正在抛出OutOfMemoryException读取大(1 GB) XML文件的一部分
EN

Stack Overflow用户
提问于 2017-10-06 18:46:02
回答 2查看 729关注 0票数 3

我正在处理一个很大的XML文件,在运行应用程序时,XmlTextReader.ReadOuterXml()方法抛出了内存异常。

代码行是这样的,

代码语言:javascript
复制
XmlTextReader xr = null;
try
{
    xr = new XmlTextReader(fileName);
    while (xr.Read() && success)
    {
        if (xr.NodeType != XmlNodeType.Element) 
            continue;
        switch (xr.Name)
        {
            case "A":
                var xml = xr.ReadOuterXml();
                var n = GetDetails(xml);
                break;
        }
    }
}
catch (Exception ex)
{
    //Do stuff
}

使用:

代码语言:javascript
复制
private int GetDetails (string xml)
{

    var rootNode = XDocument.Parse(xml);
    var xnodes = rootNode.XPathSelectElements("//A/B").ToList();
    //Then  working on list of nodes

}

现在,当加载XML文件时,应用程序在xr.ReadOuterXml()行抛出异常。如何避免这种情况呢?的大小几乎是1 GB。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2017-10-08 15:08:20

ReadOuterXml()中获得OutOfMemoryException的最有可能的原因是,您试图将1 GB的XML文档中的很大一部分读入到字符串中,并且命中Maximum string length in .Net

所以,不要这样做。使用XDocument.Load()XmlReader.ReadSubtree()直接从XmlReader加载

代码语言:javascript
复制
using (var xr = XmlReader.Create(fileName))
{
    while (xr.Read() && success)
    {
        if (xr.NodeType != XmlNodeType.Element)
            continue;
        switch (xr.Name)
        {
            case "A":
                {
                    // ReadSubtree() positions the reader at the EndElement of the element read, so the 
                    // next call to Read() moves to the next node.
                    using (var subReader = xr.ReadSubtree())
                    {
                        var doc = XDocument.Load(subReader);
                        GetDetails(doc);
                    }
                }
                break;
        }
    }
}

然后在GetDetails()中执行以下操作:

代码语言:javascript
复制
private int GetDetails(XDocument rootDocument)
{
    var xnodes = rootDocument.XPathSelectElements("//A/B").ToList();
    //Then  working on list of nodes
    return xnodes.Count;
}

这不仅会使用更少的内存,而且还会有更高的性能。ReadOuterXml()使用临时XmlWriter将输入流中的XML复制到输出StringWriter (然后对其进行第二次解析)。这个版本的算法完全跳过了这个额外的工作。它还避免了创建足够大的字符串以在large object heap上运行,这可能会导致额外的性能问题。

如果这仍然使用了太多的内存,那么您将需要为您的实现SAX-like解析,一次只加载一个元素<B>。首先,介绍下面的扩展方法:

代码语言:javascript
复制
public static partial class XmlReaderExtensions
{
    public static IEnumerable<XElement> WalkXmlElements(this XmlReader xmlReader, Predicate<Stack<XName>> filter)
    {
        Stack<XName> names = new Stack<XName>();

        while (xmlReader.Read())
        {
            if (xmlReader.NodeType == XmlNodeType.Element)
            {
                names.Push(XName.Get(xmlReader.LocalName, xmlReader.NamespaceURI));
                if (filter(names))
                {
                    using (var subReader = xmlReader.ReadSubtree())
                    {
                        yield return XElement.Load(subReader);
                    }
                }
            }

            if ((xmlReader.NodeType == XmlNodeType.Element && xmlReader.IsEmptyElement)
                || xmlReader.NodeType == XmlNodeType.EndElement)
            {
                names.Pop();
            }
        }
    }
}

然后,按如下方式使用它:

代码语言:javascript
复制
using (var xr = XmlReader.Create(fileName))
{
    Predicate<Stack<XName>> filter =
        (stack) => stack.Peek().LocalName == "B" && stack.Count > 1 && stack.ElementAt(1).LocalName == "A";
    foreach (var element in xr.WalkXmlElements(filter))
    {
        //Then working on the specific node.
    }
}
票数 2
EN

Stack Overflow用户

发布于 2021-03-11 23:21:26

代码语言:javascript
复制
using (var reader = XmlReader.Create(fileName))
{   
    XmlDocument oXml = new XmlDocument();
    while (reader.Read())
        {                  
            oXml.Load(reader);                    
        }
}

对于我来说,上面的代码解决了我们通过XmlDocument Load方法将其返回给XmlDocument时的问题

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/46603999

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档