2013-07-25 71 views
0

我想這個功能,去無限循環,從一個文件夾中的所有文件,並以文件的相對子文件夾複製到另一個位置:避免定製複製目錄功能複製文件夾時爲自己

using System.IO; 

private static bool CopyDirectory(string SourcePath, string DestinationPath, bool overwriteexisting) 
     { 
      bool ret = true; 
      try 
      { 
       SourcePath = SourcePath.EndsWith(@"\") ? SourcePath : SourcePath + @"\"; 
       DestinationPath = DestinationPath.EndsWith(@"\") ? DestinationPath : DestinationPath + @"\"; 

       if (Directory.Exists(SourcePath)) 
       { 
        if (Directory.Exists(DestinationPath) == false) 
         Directory.CreateDirectory(DestinationPath); 

        foreach (string fls in Directory.GetFiles(SourcePath)) 
        { 
         FileInfo flinfo = new FileInfo(fls); 
         flinfo.CopyTo(DestinationPath + flinfo.Name, overwriteexisting); 
        } 

        foreach (string drs in Directory.GetDirectories(SourcePath)) 
        { 
         DirectoryInfo drinfo = new DirectoryInfo(drs); 
         if (CopyDirectory(drs, DestinationPath + drinfo.Name, overwriteexisting) == false || drs.Substring(drs.Length-8) == "archive") 
          ret = false; 
        } 
       } 
       else 
       { 
        ret = false; 
       } 
      } 
      catch (Exception e) 
      { 
       Console.WriteLine("{0} {1} {2}", e.Message, Environment.NewLine + Environment.NewLine, e.StackTrace); 
       ret = false; 
      } 
      return ret; 
     } 

它工作良好,直到你必須將文件夾複製到另一個位置,但是當你必須自己創建一個文件夾時(在我的例子中,我正在做一個名爲「archive」的子文件夾來跟蹤最後一次文件夾文件的變化)在無限循環中,因爲它在Directory.GetDirectories foreach循環中不斷重新掃描,找到新創建的子文件夾並反覆嵌套相同的子文件夾,直到它達到「路徑名太長max 260 charachters limit例外」。

我試圖通過使用條件

,以避免它|| drs.Substring(drs.Length-8)==「archive」)

它應該檢查目錄名稱,但它似乎不起作用。

我認爲,不同的解決方案,如把最大子文件夾深度掃描(I.E最大2子文件夾),所以它不會重新掃描所有嵌套的文件夾,但我無法在目錄對象中找到這樣的屬性。

我無法將整個事物複製到臨時文件夾,然後進入實際文件夾,因爲下次掃描它時,它也會重新掃描存檔文件夾。

我把所有的目錄列表放在Directory對象的ArrayList中,所以也許我可以檢查像DirName這樣的東西,但我不知道這樣的屬性是否存在。

任何解決方案?

+0

子之前已經嘗試過,沒有運氣。即使比較從調試器獲得的確切字符串值也不會導致結果。 –

回答

0

這種情況下,遞歸併不真正起作用,因爲目錄和文件列表在複製時總是變化。更好的解決方案是提前獲取所有文件和文件夾的列表。

您可以使用Directory.GetFiles(String,String,SearchOption)Directory.GetDirectories(String,String,SearchOption)將樹中的所有文件和目錄設置爲樹狀,並將SearchOption設置爲SearchOption.AllDirectories。這些將分別返回所有文件和所有目錄。

您可以按照以下步驟來複制文件:

  1. 獲取所有源目錄的列表並以升序進行排序。這將確保父目錄出現在其子目錄之前。
  2. 通過按排序順序創建子目錄來創建目標目錄結構。由於排序順序可確保始終在子文件夾之前創建父文件夾,因此您不會遇到任何路徑衝突
  3. 像以前一樣將所有源文件複製到目標目錄。由於目標目錄結構已經存在,訂單在這一點上並不重要。

一個簡單的例子:

static void Main(string[] args) 
    { 
     var sourcePath = @"c:\MyRoot\TestFolder\"; 

     var targetPath = @"c:\MyRoot\TestFolder\Archive\"; 

     var directories=Directory.GetDirectories(sourcePath, "*", SearchOption.AllDirectories); 
     var files = Directory.GetFiles(sourcePath, "*", SearchOption.AllDirectories); 

     if(!Directory.Exists(targetPath)) 
      Directory.CreateDirectory(targetPath); 

     foreach (var directory in directories) 
     { 
      var relativePath = GetRelativePath(sourcePath, directory); 
      var toPath = Path.Combine(targetPath, relativePath); 
      if (!Directory.Exists(toPath)) 
      { 
       Directory.CreateDirectory(toPath); 
      } 
     } 

     foreach (var file in files) 
     { 
      var relativePath = GetRelativePath(sourcePath, file); 
      var toPath = Path.Combine(targetPath, relativePath); 
      if (!File.Exists(toPath)) 
       File.Copy(file,toPath); 
     } 
    } 

    //This is a very quick and dirty way to get the relative path, only for demo purposes etc 
    private static string GetRelativePath(string rootPath, string fullPath) 
    { 
     return Path.GetFullPath(fullPath).Substring(rootPath.Length); 
    }