2017-04-21 117 views
1

我有一個任務是創建帶有功能的Windows窗體,以創建文件和文件夾層次結構的XML文件。我確實設法做到了,但遇到了一些麻煩。這裏是我的代碼:從目錄樹中生成XML時發生遞歸問題

public static XElement xmlTreeView(DirectoryInfo dir) 
    { 
     XDocument xmlDocument = new XDocument(
      new XDeclaration("1.0", "utf-8", "yes"), 
      new XComment("Create an XML file containing complete hierarchy of files and folders for a specified folder")); 

     var info = new XElement("Directory", new XAttribute("name", dir.Name)); 

     foreach (var subDir in dir.GetDirectories()) 
     { 
      info.Add(new XElement("SubDirectory", new XAttribute("name", subDir.Name), 
       new XElement("FilesInFolder", subDir.GetFiles().Length))); 
      foreach (var file in subDir.GetFiles()) 
       { 
        info.Add(new XElement("File", new XAttribute("name", file.Name), 
         new XElement("Size", file.Length), 
         new XElement("CreationTime", file.CreationTime), 
         new XElement("LastAccess", file.LastAccessTime), 
         new XElement("LastModified", file.LastWriteTime))); 
      } 
     } 

     foreach (var file in dir.GetFiles()) 
     { 
      info.Add(new XElement("File", new XAttribute("name", file.Name), 
       new XElement("Size", file.Length), 
       new XElement("CreationTime", file.CreationTime), 
       new XElement("LastAccess", file.LastAccessTime), 
       new XElement("LastModified", file.LastWriteTime))); 
     } 



     return info; 
    } 

的問題是,每個文件夾必須大小和多少文件所在的文件夾中。我試圖計算文件夾的大小,但我不能。我能夠顯示子文件夾中有多少文件,但所有這些文件都不會顯示在XElement「SubDirectory」中。如果我刪除子目錄中的第二個foreach,而不是甚至沒有顯示的文件。請幫助。

+0

好問題,你應該給它一個更好的標題! – Aybe

+0

第一個問題...... :)不知道如何命名它...... –

+0

好吧,繼續,爲你製作一些東西! – Aybe

回答

0

下面的程序將建立一個XML樹了一個基本目錄:

using System.Collections.Generic; 
using System.IO; 
using System.Linq; 
using System.Xml.Linq; 

namespace ConsoleApplication1 
{ 
    internal class Program 
    { 
     private static void Main(string[] args) 
     { 
      ConvertToXml(@"C:\test"); 
     } 

     private static void ConvertToXml(string baseDirectory) 
     { 
      var root = new XElement("Root"); 

      var queue = new Queue<KeyValuePair<XElement, string>>(); 
      queue.Enqueue(new KeyValuePair<XElement, string>(root, baseDirectory)); 

      while (queue.Any()) 
      { 
       var pair = queue.Dequeue(); 
       var path = pair.Value; 
       var element = pair.Key; 
       var directories = Directory.GetDirectories(path); 
       var files = Directory.GetFiles(path); 

       element.Add(
        new XAttribute("Files", files.Length.ToString()), 
        new XAttribute("Directories", directories.Length.ToString())); 

       foreach (var directory in directories) 
       { 
        var directoryInfo = new DirectoryInfo(directory); 
        var directoryElement = new XElement("Directory", 
         new XAttribute("Name", directoryInfo.Name), 
         new XAttribute("Size", GetDirectorySize(directory))); 

        element.Add(directoryElement); 
        queue.Enqueue(new KeyValuePair<XElement, string>(directoryElement, directory)); 
       } 

       foreach (var file in files) 
       { 
        var fileInfo = new FileInfo(file); 
        var fileElement = new XElement("File", 
         new XAttribute("Name", fileInfo.Name), 
         new XAttribute("Size", fileInfo.Length)); 
        element.Add(fileElement); 
       } 
      } 

      var xml = root.ToString(); 
     } 

     private static long GetDirectorySize(string path) 
     { 
      long length = 0; 

      var queue = new Queue<string>(new[] {path}); 

      while (queue.Any()) 
      { 
       var value = queue.Dequeue(); 

       var files = Directory.GetFiles(value); 
       length += files.Sum(s => new FileInfo(s).Length); 

       var directories = Directory.GetDirectories(value); 
       foreach (var directory in directories) 
        queue.Enqueue(directory); 
      } 

      return length; 
     } 
    } 
} 

結果:

<Root Files="0" Directories="1"> 
    <Directory Name="root" Size="444" Files="1" Directories="2"> 
    <Directory Name="folder1" Size="148" Files="1" Directories="0"> 
     <File Name="document1.txt" Size="148" /> 
    </Directory> 
    <Directory Name="folder2" Size="185" Files="1" Directories="0"> 
     <File Name="document2.txt" Size="185" /> 
    </Directory> 
    <File Name="readme.txt" Size="111" /> 
    </Directory> 
</Root> 

注:

  • ñ Ø遞歸(這是很好的IMO)
  • 計算目錄大小可長期
  • 根據不同的目錄中,可能有一些ACL阻止你訪問它
  • 只是一個簡單的例子 - >你需要
  • 什麼增加它
+0

這真的很好,謝謝你,至少你解決了我的尺寸問題。但我所做的程序必須以窗口形式。這可以應用於它嗎?並且仍然需要一個文件夾中有多少個文件... –

+0

對於任何非標準(LINQ,XML)都沒有依賴關係,也就是說,只要有.NET 4,就可以使用該代碼,因此在表單中它將起作用。 (和我剛剛添加文件夾/文件計數) – Aybe

+0

我只是試過了,它的工作原理。你是一個救星! :) 再次感謝你! –

0

如果你在VB這樣它看起來像

Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click 
    Dim path As String = Environment.GetFolderPath(Environment.SpecialFolder.Desktop) 
    Dim di As New IO.DirectoryInfo(path) 
    Dim dirXML As XElement = XMLTreeView(di) 

    Dim totalFiles As Integer = (From el In dirXML...<FilesInFolder> 
            Let tf = Integer.Parse(el.Value) 
            Select tf).Sum 

    Dim totalLength As Long = (From el In dirXML...<Size> 
           Let tl = Long.Parse(el.Value) 
           Select tl).Sum 
End Sub 

Private Function XMLTreeView(dir As IO.DirectoryInfo) As XElement 
    Dim base As XElement = <Directory name=<%= dir.Name %>> 
          </Directory> 

    DoSubDirs(dir, base) 
    Return base 
End Function 

Private Sub DoSubDirs(dir As IO.DirectoryInfo, info As XElement) 
    For Each di As IO.DirectoryInfo In dir.GetDirectories 
     Try 
      Dim subXE As XElement = <SubDirectory name=<%= di.Name %>> 
             <FilesInFolder><%= di.GetFiles.Length.ToString %></FilesInFolder> 
            </SubDirectory> 
      For Each fi As IO.FileInfo In di.GetFiles 
       Dim fileXE As XElement = <File name=<%= fi.Name %>> 
             </File> 
       IncludeInfo(fi, fileXE) 
       subXE.Add(fileXE) 
      Next 
      DoSubDirs(di, subXE) 
      info.Add(subXE) 
     Catch ex As Exception 
      'todo errors 
      'probably permissions 
     End Try 
    Next 
End Sub 

Private Sub IncludeInfo(info As IO.FileInfo, xe As XElement) 
    xe.Add(<Attributes><%= info.Attributes %></Attributes>) 
    xe.Add(<Size><%= info.Length %></Size>) 
    xe.Add(<CreationTime><%= info.CreationTime %></CreationTime>) 
    xe.Add(<LastAccess><%= info.LastAccessTime %></LastAccess>) 
    xe.Add(<LastModified><%= info.LastWriteTime %></LastModified>) 
End Sub 

遞歸通常不與文件系統的問題,因爲嵌套的水平也不是很大。

如果我是C#程序員,我會使用VB模塊進行XML,因爲它使用XML文字的能力。

+0

在C#中使用XML文字是**不可能**! – Aybe

+0

我知道,他們很方便。不知道爲什麼他們被排除在C#之外。 – dbasnett