2012-06-08 98 views
29

我正在讀C#的一些文件IO教程,並設法寫出一些文件,但如果我給出的路徑包含目錄怎麼辦?創建文件,遞歸創建目錄

例如,我想創建名爲data/my_file的文件,但data文件夾不存在。

線,

BinaryWriter outFile = new BinaryWriter(File.OpenWrite(path)); 

其中path是上面的字符串,與消息的路徑的一部分不存在,這意味着根據需要C#不創建它們崩潰。

我想C#來處理所有的混亂的目錄創建和檢查我而不是我必須解析路徑並創建所有必要的目錄。這可能嗎?否則,是否有一段代碼可以複製到我的項目中,該項目將處理任何我可能忽略的內容(因爲我對文件管理了解不多)。

+0

你不需要用 「C#」 的前綴您的標題。 \t 請參閱「[堆棧溢出不需要你的SEO技巧](http://meta.stackexchange.com/a/130208)」。 –

回答

69

System.IO.Directory.CreateDirectory()將創建指定路徑中的所有目錄和子目錄,如果它們不存在。

您可以調用它,傳遞路徑,以確保在編寫文件之前創建文件夾結構。

+0

太棒了!雖然現在我有點想知道爲什麼這不是自動完成的。我的意思是,有些時候你不想自動創建這些目錄,如果需要的話? – MxyL

+10

微軟至少會提供一個布爾參數給BinaryWriter,詢問你是否想創建不存在的目錄。我想如果你總是這樣做,那麼有人會有一個用例,他們不想要這種行爲,並會抱怨他們無法控制它。 –

+0

考慮到'Directory.GetFiles()'具有'SearchOption'指定頂級搜索或遞歸搜索,他們沒有包含這樣的參數是很好奇的。 – Erik

7

儘管System.IO.Directory.CreateDirectory()確實會遞歸地爲您創建目錄,但是我遇到了必須提出自己的方法的情況。基本上System.IO不支持超過260個字符的路徑,這迫使我使用Delimon.Win32.IO庫,它使用長路徑,但不會遞歸地創建目錄。

下面是我用遞歸創建目錄代碼:

void CreateDirectoryRecursively(string path) 
{ 
    string[] pathParts = path.Split('\\'); 

    for (int i = 0; i < pathParts.Length; i++) 
    { 
     if (i > 0) 
      pathParts[i] = Path.Combine(pathParts[i - 1], pathParts[i]); 

     if (!Directory.Exists(pathParts[i])) 
      Directory.CreateDirectory(pathParts[i]); 
    } 
} 
+2

不在超過255個字符的路徑上瀏覽barf?它很爛,但我會盡快截斷它,而不是試圖處理那些廢話。 – Casey

+1

2年前的凹凸我知道,但我偶然發現了這個答案,同時修復了一個錯誤,並且想給這個答案添加警告。當使用網絡驅動器時(路徑以\\\開頭),這將拋出「路徑不是合法形式」。 –

+0

如果路徑包含驅動器號,代碼也會失敗。 – Hans

1

所以,上面並沒有爲我的基本目錄的創建工作以及超強。我修改了這一點,以處理常見的情況下的驅動器號和末尾的文件資源的路徑。

public bool CreateDirectoryRecursively(string path) 
    { 
     try 
     { 
      string[] pathParts = path.Split('\\'); 
      for (var i = 0; i < pathParts.Length; i++) 
      { 
       // Correct part for drive letters 
       if (i == 0 && pathParts[i].Contains(":")) 
       { 
        pathParts[i] = pathParts[i] + "\\"; 
       } // Do not try to create last part if it has a period (is probably the file name) 
       else if (i == pathParts.Length-1 && pathParts[i].Contains(".")) 
       { 
        return true; 
       } 
       if (i > 0) { 
        pathParts[i] = Path.Combine(pathParts[i - 1], pathParts[i]); 
       } 
       if (!Directory.Exists(pathParts[i])) 
       { 
        Directory.CreateDirectory(pathParts[i]); 
       } 
      } 
      return true; 
     } 
     catch (Exception ex) 
     { 
      var recipients = _emailErrorDefaultRecipients; 
      var subject = "ERROR: Failed To Create Directories in " + this.ToString() + " path: " + path; 
      var errorMessage = Error.BuildErrorMessage(ex, subject); 
      Email.SendMail(recipients, subject, errorMessage); 
      Console.WriteLine(errorMessage); 
      return false; 

     } 

    } 
0

以前的答案沒有處理網絡路徑。 附加的代碼也處理。

/// <summary> 
/// tests (and creates missing) directories in path containing many 
subDirectories which might not exist. 
    /// </summary> 
    /// <param name="FN"></param> 
    public static string VerifyPath(string FN, out bool AllOK) 
    { 
     AllOK = true; 
     var dir = FolderUtils.GetParent(FN); 
     if (!Directory.Exists(dir))//todo - move to folderUtils.TestFullDirectory 
     { 
      const char DIR = '\\'; 
      //string dirDel = "" + DIR; 

      string[] subDirs = FN.Split(DIR); 
      string dir2Check = ""; 
      int startFrom = 1;//skip "c:\" 
      FN = CleanPathFromDoubleSlashes(FN); 
      if (FN.StartsWith("" + DIR + DIR))//netPath 
       startFrom = 3;//FN.IndexOf(DIR, 2);//skip first two slashes.. 
      for (int i = 0; i < startFrom; i++) 
       dir2Check += subDirs[i] + DIR;//fill in begining 

      for (int i = startFrom; i < subDirs.Length - 1; i++)//-1 for the file name.. 
      { 
       dir2Check += subDirs[i] + DIR; 
       if (!Directory.Exists(dir2Check)) 
        try 
        { 
         Directory.CreateDirectory(dir2Check); 
        } 
        catch { AllOK = false; } 
      } 
     } 
     if (File.Exists(FN)) 
      FN = FolderUtils.getFirstNonExistingPath(FN); 
     if (FN.EndsWith("\\") && !Directory.Exists(FN)) 
      try { Directory.CreateDirectory(FN); } 
      catch 
      { 
       HLogger.HandleMesssage("couldn't create dir:" + FN, TypeOfExceptions.error, PartsOfSW.FileStructure); 
       AllOK = false; 
      } 

     return FN; 

    } 

與 「CleanDoubleSlashes功能」:

public static string CleanPathFromDoubleSlashes(string basePath) 
    { 
     if (string.IsNullOrEmpty(basePath) || basePath.Length < 2)//don't clean first \\ of LAN address 
      return basePath; 
     for (int i = basePath.Length - 1; i > 1; i--) 
     { 
      if ((basePath[i] == '\\' && basePath[i - 1] == '\\') || (basePath[i] == '/' && basePath[i - 1] == '/')) 
      { 
       basePath = basePath.Remove(i, 1);//Substring(0, i - 2) + basePath.Substring(i, basePath.Length - 1 - i); 
      } 
     } 
     return basePath; 
    }