2013-04-30 51 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