2012-06-08 129 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; 
    }