2013-04-30 43 views
1

我有一段代码,它适用于正常的文件。但对于真正的大文件,它会使服务器停止工作。阅读大型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 
{ } 

我认为这是导致其发生在服务器上的内存问题的一部分。我怎样才能解决这个问题?

+0

有多少个'transact'元素? (这可能甚至不可行...) – 2013-04-30 06:02:38

+0

你能否告诉我们导致错误的文件的大小?它是单个文件还是多个大文件? – Jras 2013-04-30 06:07:10

+0

@JonSkeet 8.000 – 2013-04-30 06:07:24

回答

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

注意:这里假定从来没有任何其他级别的“交易”元素。如果有的话,您需要更仔细地使用您的XmlReader,而不只是拨打ReadToFollowing。另外请注意,您需要找到eanucc别名的实际名称空间URI。

不要忘记,如果您尝试一次性阅读全部这个信息(例如,通过调用ToList()),那么您仍然会用完内存。您需要的信息。 (目前还不清楚你想要做什么,但你需要仔细考虑。)

+0

我试图对它们进行计数,以找出文件中有多少个事务处理元素。我将如何调用ReadTransactions()? – 2013-04-30 06:26:02

+1

@petko_stankoski:如果你只是*想要数它们,你根本不需要加载它们。我希望你之前说过。也就是说,你总是可以使用'int count = ReadTransactions.Count();' – 2013-04-30 07:17:22

+0

Tnx,你真的帮了忙。但reader.ReadSubtree()返回空。 – 2013-04-30 07:23:50

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 
{ } 
+2

在你的答案中提供了更多细节。避免一行/简短的答案。不要在你的回答中提问,为此目的使用评论。 – Freelancer 2013-04-30 06:02:36