2012-06-08 88 views
29

C#のファイルIOチュートリアルを読んでいて、いくつかのファイルを書き出していましたが、与えられたパスにディレクトリが含まれているとどうなりますか?ファイルの作成、再帰的なディレクトリの作成

たとえば、dataというフォルダが存在しないことを除き、data/my_fileというファイルを作成したいとします。

線、pathは、上記文字列であり、必要に応じて、C#は、それらを作成しないことを意味パスの一部が存在しないメッセージでクラッシュし

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

私は、C#で、いたずらにディレクトリを作成し、パスを解析して必要なディレクトリをすべて作成するのではなく、私をチェックすることをお勧めします。これは可能ですか?さもなければ、コードのスニペットがあります。私はプロジェクトにコピーして、私が見落としているかもしれないものを扱います(ファイル管理についてはあまり知らないので)。

+0

。 \t 「[スタックオーバーフローはあなたのSEOスキルが必要ではありません](http://meta.stackexchange.com/a/130208)」を参照してください。 –

答えて

69

System.IO.Directory.CreateDirectory()は、指定されたパスにすべてのディレクトリとサブディレクトリを作成します(存在しない場合)。

ファイルを書き込む前に、フォルダ構造を確実に作成するためにパスを渡して呼び出すことができます。

+0

素晴らしい!現在、私はなぜこれが自動的に行われないのか不思議です。つまり、必要に応じて自動的にこれらのディレクトリを実際に作成したくない場合がありますか? – MxyL

+10

BinaryWriterに少なくともブール値パラメータを提供して、存在しない場合にディレクトリを作成するかどうかを尋ねるのは、Microsoftにとっては本当に便利でした。私はあなたがいつもそれをやるかどうか、誰かがその行動を望んでいないユースケースを持ち、彼らがそれを支配していないと不満を持ちます。 –

+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文字を超えるエクスプローラバーフはありませんか?それは吸うが、私はすぐにそれを切り捨てて、そのくそに対処しようとしているより。 – Casey

+1

2y古いバンプ知っていますが、バグを修正している間にこの答えにつきものがあり、この回答に警告を追加したかったのです。ネットワークドライブ(\\\で始まるパス)を使用している場合、これは "パスは正式な形式ではありません"。 –

+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機能":あなたは "C#の" とのタイトルの前に付ける必要はありません

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; 
    } 
関連する問題