gpt4 book ai didi

c# - ReadOuterXml 正在读取大型 (1 GB) XML 文件的一部分时抛出 OutOfMemoryException

转载 作者:数据小太阳 更新时间:2023-10-29 02:38:48 24 4
gpt4 key购买 nike

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

代码行就像,

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
}

使用:

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() 行抛出异常。可以做些什么来避免这种情况? XML 的大小将近 1 GB。

最佳答案

您收到 OutOfMemoryException 的最可能原因在ReadOuterXml()是您试图将 1 GB XML 文档的大部分读入字符串,并且正在点击 Maximum string length in .Net .

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

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()做:

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解析您的 XML,您只加载一个元素 <B>一次。首先介绍一下扩展方法:

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

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

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.
}
}

关于c# - ReadOuterXml 正在读取大型 (1 GB) XML 文件的一部分时抛出 OutOfMemoryException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46603999/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com