C#操作XML(四)

來源:互聯網
上載者:User

標籤:

一、上篇回顧

  上兩篇都介紹了Linq to Xml的相關用法,需要注意的一點是Linq to Xml是in-memory的處理方式,所以有多少節點,就要消耗多少記憶體,如果這個Xml很大,但系統記憶體卻有限的情況下該怎麼辦呢?

  下面我們就來一步步分析。

二、設定與實現目標

  今天要做的是把某目錄下的所有檔案和目錄輸出到一個Xml裡面去,例如:  

<?xml version="1.0" encoding="gb2312"?><folder name="bin">  <folder name="Debug">    <file name="ConsoleApplication6.exe" />    <file name="ConsoleApplication6.exe.config" />    <file name="ConsoleApplication6.pdb" />    <file name="ConsoleApplication6.vshost.exe" />    <file name="ConsoleApplication6.vshost.exe.config" />    <file name="ConsoleApplication6.vshost.exe.manifest" />  </folder>  <folder name="Release">    <file name="ConsoleApplication6.exe" />    <file name="ConsoleApplication6.exe.config" />    <file name="ConsoleApplication6.pdb" />    <file name="ConsoleApplication6.vshost.exe" />    <file name="ConsoleApplication6.vshost.exe.config" />    <file name="ConsoleApplication6.vshost.exe.manifest" />  </folder></folder>

1. 使用Linq to Xml嘗試

  如果使用之前介紹的Linq to Xml可以很快寫出一下代碼:

static void Main(string[] args){    var di = new DirectoryInfo("E:\\PDF");    XDocument doc = new XDocument(GetFolderContent(di));                doc.Save(Console.Out);    Console.ReadKey();}private static XElement GetFolderContent(DirectoryInfo di){    return new XElement("folder",        new XAttribute("name", di.Name),        from subDir in di.GetDirectories()        select GetFolderContent(subDir),        from file in di.GetFiles()        select new XElement("file", new XAttribute("name", file.Name))        );}

  但是要注意一點,Linq to Xml是in-memory的方式工作的,也就是如果有1000級的目錄嵌套,沒級有100個子目錄,那麼久有100^1000個XElement在記憶體中建立出來。好吧,這麼計算一下,整個過程需要多少記憶體吧,10的2000次方*每一個XElement消耗的記憶體,就算只有1Byte,1G記憶體也只能處理10的30次方,所以要處理完這個情境,需要多少記憶體啊!可以說是不可能達到的。

2. 分析

  上面的實現得益於Linq to Xml Api的簡易,但是卻受制於Linq to Xml的in-memory模型,要是有一種既可以受益於Linq to Xml的簡易,又可以使用非in-memory的模型就兩全其美了。

  天下有這麼好的事情嗎?先不要急於下定論,讓我們來查查msdn吧:如何:執行大型 XML 文檔的流式轉換。

  這裡提到了一個XStreamingElement的類,僅僅從名稱上,就可以猜到,這個類是一個類似XElement的類型,但是它又是一個類似Stream的類,並不是in-memory的,當然具體怎麼說還要看msdn。

  msdn中有明確說明:表示支援延遲流輸出的XML樹中的元素。

  而且備忘中說到:如果從輸入源(和文字檔)進行串流,則可以讀取非常大的文字檔,並產生非常大的XML文檔,同事保持較小的記憶體需求量。

  也就是明確了XStremingElement的這個類本身就是(或類似)串流的,並不像普通的XElement的in-memory的處理方式。


3. 實現

  找到了XStreamingElement這個Linq to Xml的另類API後,就可以實現前面的目標了。

  XStreamingElement的用法與XElement十分相似,只需要把前面的方法稍作修改即可:  

private static XStreamingElement GetFolderContent(DirectoryInfo di){    return new XStreamingElement("folder",        new XAttribute("name", di.Name),        from subDir in di.GetDirectories()        select GetFolderContent(subDir),        from file in di.GetFiles()        select new XElement("file", new XAttribute("name", file.Name))        );}

  不過需要額外修改一下外面的調用方式:

var di = new DirectoryInfo("d:\\sourcecode");GetFolderContent(di).Save(Console.Out);

  注意:這裡必須要用XStreamingElement的Save方法,否則延遲求解的特性可能會失敗。

三、總結

  本篇介紹了Linq to Xml中的異類:XStreamingElement,既得益於Linq to Xml的簡易,又擁有streaming的小記憶體特性,在操作超大Xml時這兩個特性可以讓工作事半功倍。

C#操作XML(四)

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.