2012-06-08 29 views
29

Estaba leyendo algunos tutoriales de IO de archivos para C# y he logrado escribir algunos archivos, pero ¿qué ocurre si la ruta que tengo contiene directorios?crear archivos, crear directorios recursivamente

Por ejemplo, quiero crear el archivo llamado data/my_file excepto que la carpeta data no existe.

La línea,

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

donde path es la cadena de más arriba, se bloquea con el mensaje de que no existe parte de la trayectoria, lo que significa C# no está creando ellos según sea necesario.

Me gustaría que C# maneje toda la creación de directorios desordenados y me busque en lugar de tener que analizar la ruta y crear todos los directorios necesarios. es posible? De lo contrario, hay un fragmento de código que puedo copiar en mi proyecto que manejará cualquier cosa que pueda estar pasando por alto (ya que no sé mucho sobre administración de archivos).

+0

No es necesario anteponer el título con "C#". \t Consulte "[Stack Overflow no necesita sus habilidades de SEO] (http://meta.stackexchange.com/a/130208)". –

Respuesta

69

System.IO.Directory.CreateDirectory() creará todos los directorios y subdirectorios en una ruta especificada, en caso de que no existan.

Puede llamarlo, pasando la ruta, para asegurarse de que la estructura de la carpeta se crea antes de escribir su archivo.

+0

¡Genial! Aunque ahora me pregunto por qué esto no se hace automáticamente. Quiero decir, ¿hay momentos en los que no desea realmente crear estos directorios automáticamente si es necesario? – MxyL

+10

Hubiera sido realmente útil para Microsoft al menos proporcionar un parámetro booleano a BinaryWriter que pregunta si desea crear los directorios si no existen. Supongo que si * siempre * lo haces, alguien tendrá un caso de uso en el que no quiera ese comportamiento y se quejará de que no tiene control sobre él. –

+0

Es curioso que no incluyan dicho parámetro, considerando 'Directory.GetFiles()' tiene 'SearchOption' para especificar la búsqueda recursiva o de nivel superior. – Erik

7

Si bien System.IO.Directory.CreateDirectory() de hecho creará directorios para usted recursivamente, me encontré con una situación en la que tuve que idear mi propio método. Básicamente, System.IO no admite rutas de más de 260 caracteres, lo que me obligó a usar la biblioteca Delimon.Win32.IO, que funciona con rutas largas, pero no crea directorios recursivamente.

Aquí está el código que he usado para la creación de directorios de forma recursiva:

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

¿No explora Barf en rutas de más de 255 caracteres? Apesta, pero preferiría truncarlo antes que tratar de manejar esa mierda. – Casey

+1

2y bache viejo lo sé, pero me encontré con esta respuesta mientras solucionaba un error y quería agregar una advertencia a esta respuesta. Esto arrojará "La ruta de acceso no es de una forma legal" cuando se utilizan unidades de red (Rutas que comienzan con \\\). –

+0

El código también fallará si la ruta contiene la letra de la unidad. – Hans

1

Por lo tanto, lo anterior no funcionó muy bien para mí para la creación de directorios básica. Modifiqué esto un poco para manejar casos comunes de letras de unidad y una ruta con un recurso de archivo al final.

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

Las respuestas anteriores no manejaban las rutas de red. Código adjunto que también maneja eso.

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

    } 

Y la "función 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; 
    } 
Cuestiones relacionadas