读取大型xml文件会使服务器停止工作 - 内存不足

时间:2013-04-30 05:54:35

标签: c# xml

我有一段适用于普通文件的代码。但对于非常大的文件,它会使服务器停止工作。

这是:

XmlReader reader = null;
try
{
    reader = XmlReader.Create(file_name + ".xml");
    XDocument xml = XDocument.Load(reader);
    XmlNamespaceManager namespaceManager = GetNamespaceManager(reader);
    XElement root = xml.Root;

    //XAttribute supplier = root.XPathSelectElement("//sh:Receive/sh:Id", namespaceManager).Attribute("Authority");

    //string version = root.XPathSelectElement("//sh:DocumentId/sh:Version", namespaceManager).Value;

    var nodes = root.XPathSelectElements("//eanucc:msg/eanucc:transact", namespaceManager);

    return nodes;                
}
catch
{ }

我认为这是导致服​​务器上发生内存问题的部分。我该如何解决这个问题?

2 个答案:

答案 0 :(得分:3)

听起来好像只有太多的数据可以一次读取。您必须一次迭代一个元素,使用XmlReader作为游标,并一次将一个元素转换为XElement

public static IEnumerable<XElement> ReadTransactions()
{
    using (var reader = XmlReader.Create(file_name + ".xml"))
    {
        while (reader.ReadToFollowing("transact", eanuccNamespaceUri))
        {
            using (var subtree = reader.ReadSubtree())
            {
                yield return XElement.Load(subtree);
            }
        }
    }
}

注意:这假设在任何其他级别都没有“transact”元素。如果有,您需要更加谨慎对待XmlReader,而不仅仅是致电ReadToFollowing。另请注意,您需要找到eanucc别名的实际名称空间URI。

不要忘记,如果您尝试一次性阅读所有此信息(例如通过调用ToList()),那么您仍然会耗尽内存。您需要流式传输信息。 (目前还不清楚你要对这些元素做些什么,但你需要仔细考虑它。)

答案 1 :(得分:0)

尝试将阅读器放入using(){}子句中,以便在使用后将其处理掉。

try
{
    using(var reader = XmlReader.Create(file_name + ".xml"))
    {
      XDocument xml = XDocument.Load(reader);
      XmlNamespaceManager namespaceManager = GetNamespaceManager(reader);
      XElement root = xml.Root;

      var nodes = root.XPathSelectElements("//eanucc:msg/eanucc:transact", namespaceManager);

      return nodes;
    }                
}
catch
{ }