2012-06-08 28 views
29

Ich habe einige Datei IO Tutorials für C# gelesen und habe es geschafft, einige Dateien zu schreiben, aber was ist, wenn der Pfad, den ich gebe Verzeichnisse enthält?Erstellen von Dateien, rekursiv Erstellen von Verzeichnissen

Zum Beispiel möchte ich die Datei namens data/my_file erstellen, außer data Ordner existiert nicht.

Die Linie,

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

wo path die obige Zeichenfolge ist, stürzt mit der Nachricht, die Teil des Pfades nicht existiert, was bedeutet, C# schafft sie nicht, wie erforderlich.

Ich möchte C# alle die unordentliche Verzeichniserstellung und Überprüfung für mich behandeln, anstatt mich den Pfad zu analysieren und alle erforderlichen Verzeichnisse zu erstellen. Ist das möglich? Ansonsten gibt es ein Code-Snippet, das ich einfach in mein Projekt kopieren kann, das alles behandelt, was ich übersehen könnte (da ich nicht viel über Dateiverwaltung weiß).

+0

Sie brauchen nicht Ihren Titel mit "C#" voranzustellen. \t Bitte lesen Sie "[Stack Overflow benötigt nicht Ihre SEO-Fähigkeiten] (http://meta.stackexchange.com/a/130208)". –

Antwort

69

System.IO.Directory.CreateDirectory() erstellt alle Verzeichnisse und Unterverzeichnisse in einem angegebenen Pfad, falls sie nicht bereits vorhanden sind.

Sie können es aufrufen, den Pfad übergeben, um sicherzustellen, dass die Ordnerstruktur erstellt wird, bevor Sie Ihre Datei schreiben.

+0

Großartig! Obwohl ich mich jetzt wundere, warum das nicht automatisch gemacht wird. Ich meine, gibt es Zeiten, in denen Sie diese Verzeichnisse bei Bedarf nicht automatisch erstellen möchten? – MxyL

+10

Es wäre wirklich praktisch von Microsoft gewesen, um BinaryWriter mindestens einen Boolean-Parameter bereitzustellen, der fragt, ob Sie die Verzeichnisse erstellen möchten, wenn sie nicht vorhanden sind. Ich schätze, wenn Sie * immer * es tun, wird jemand einen Anwendungsfall haben, in dem sie dieses Verhalten nicht wollten und sich beschweren, dass sie keine Kontrolle darüber haben. –

+0

Es ist seltsam, dass sie einen solchen Parameter nicht enthalten, wenn man bedenkt, dass Directory.GetFiles() '' SearchOption' hat, um die Suche auf oberster Ebene oder rekursiv zu spezifizieren. – Erik

7

Während System.IO.Directory.CreateDirectory() in der Tat rekursiv Verzeichnisse für Sie erstellt, stieß ich auf eine Situation, wo ich mit meiner eigenen Methode kommen musste. Grundsätzlich unterstützt System.IO keine Pfade über 260 Zeichen, was mich gezwungen hat, die Delimon.Win32.IO-Bibliothek zu verwenden, die mit langen Pfaden arbeitet, aber Verzeichnisse nicht rekursiv erzeugt.

Hier ist der Code, den ich rekursiv für das Erstellen von Verzeichnissen verwendet:

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

Lässt Explorer Explorer Pfade auf mehr als 255 Zeichen nicht zu? Es ist beschissen, aber ich würde es eher abschneiden als versuchen, mit diesem Mist umzugehen. – Casey

+1

2 Jahre alte Beule Ich weiß, aber ich stolperte über diese Antwort, während ich einen Fehler behob und wollte dieser Antwort eine Warnung hinzufügen. Dies führt dazu, dass "Pfad keine Rechtsform hat", wenn Netzlaufwerke verwendet werden (Pfade beginnend mit \\\). –

+0

Der Code schlägt auch fehl, wenn der Pfad den Laufwerksbuchstaben enthält. – Hans

1

Also, die oben nicht super gut für grundlegende Verzeichniserstellung für mich arbeiten. Ich habe dies ein wenig geändert, um häufige Fälle für Laufwerksbuchstaben und einen Pfad mit einer Dateiressource am Ende zu behandeln.

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

Vorherige Antworten behandelten keine Netzwerkpfade. Angehängter Code, der auch das handhabt.

/// <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; 

    } 

Und die "CleanDoubleSlashes Funktion":

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; 
    } 
Verwandte Themen