2010-04-03 28 views
38

Me encuentro haciendo esto solo para asegurarme de que el nombre de archivo no esté en uso. ¿Hay una mejor manera?Compruebe si existe un archivo/directorio: ¿hay una mejor manera?

Directory.Exists(name) || File.Exists(name) 
+1

Y lo que es malo en ello? ¿Cómo puede ser más fácil o más limpio? –

+0

Lo hago en todas partes ... es feo. Por lo general, no me preocupo por la prioridad, pero podría suceder –

+0

¿Por qué necesita estos 2 controles? ¿Por qué no usas simplemente File.Exists (name)? – Egor4eg

Respuesta

51

seguro :)

internal static bool FileOrDirectoryExists(string name) 
{ 
    return (Directory.Exists(name) || File.Exists(name)); 
} 
+1

Método de extensión para la clase Path? "Realiza operaciones en instancias String que contienen información de ruta de archivo o directorio". – si618

+0

Si. semi buena idea para tenerlo en una instancia de cadena. es realmente malo .NET no permite extender una clase estática :( –

+0

nadie lo nota; error esperado? .xD 2014ppl desde aquí, pero aún así gracias @PaulG. – Elegiac

4

creo que es la única manera. Generalmente tengo una clase "FileManager" que tiene métodos estáticos que encapsulan los métodos de E/S, incluidos los que usted indicó y luego usa ese "FileManager" en todas las aplicaciones como una biblioteca.

5

Otra forma de verificar si el archivo existe.

FileInfo file = new FileInfo("file.txt"); 

if (file.Exists) 
{ 
    // TO DO 
} 
+0

¿Dudo por qué baje el voto para esta respuesta? – Anonymous

+0

Mire las etiquetas antes de publicar una respuesta. – lsalamon

+5

La etiqueta es C#, .NET y archivo. Este es el código C# y puede generar el resultado deseado. tput. – Anonymous

29

Tenga en cuenta que el hecho de que está utilizando existe() para comprobar si el nombre de archivo o directorio en uso está sujeta a condiciones de carrera.

En cualquier momento después de que su prueba Exists() haya pasado, algo podría haber creado un archivo con ese nombre antes de que su código llegue al punto donde crea un archivo, por ejemplo.

(supongo que es una condición excepcional para que el archivo ya exista).

Es más confiable simplemente abrir el archivo, especificando un parámetro FileShare apropiado.

Ejemplo:

using System; 
using System.IO; 

static class FileNameInUse 
{ 
    static void Main(string[] args) 
    { 
     string path = args[0]; 
     using (var stream = File.Open(path, FileMode.CreateNew, FileAccess.Write, FileShare.None)) 
     { 
      // Write to file 
     } 
    } 
} 

Así que simplemente manejar el IOException en caso de fallo puede resultar en código más simple menos propenso a condiciones de carrera, porque ahora:

  • Si algo más ya ha creado el archivo , FileMode.CreateNew provocará que se arroje un IOException
  • Si su abrir y crear tiene éxito, debido a FileShare.None, ningún otro proceso puede acceder al archivo hasta que lo cierre.

Por desgracia, no es posible comprobar si un archivo está en uso, y no una excepción, sin algún feo P/Invoke:

bool IsFileInUse(string fileName) 
    { 
      IntPtr hFile = Win32.CreateFile(fileName, Win32.FILE_READ_DATA, 0, IntPtr.Zero, Win32.OPEN_EXISTING, Win32.FILE_ATTRIBUTE_NORMAL, IntPtr.Zero); 
      if (hFile.ToInt32() == Win32.INVALID_HANDLE_VALUE) 
       return true; 

      Win32.CloseHandle(hFile); 
      return false; 
    } 

    class Win32 
    { 
     const uint FILE_READ_DATA = 0x0001; 
     const uint FILE_SHARE_NONE = 0x00000000; 
     const uint FILE_ATTRIBUTE_NORMAL = 0x00000080; 
     const uint OPEN_EXISTING = 3; 
     const int INVALID_HANDLE_VALUE = -1; 

     [DllImport("kernel32.dll", SetLastError=true)] 
     internal static extern IntPtr CreateFile(string lpFileName, 
               uint dwDesiredAccess, 
               uint dwShareMode, 
               IntPtr lpSecurityAttributes, 
               uint dwCreationDisposition, 
               uint dwFlagsAndAttributes, 
               IntPtr hTemplateFile); 

     [DllImport("kernel32.dll")] 
     internal static extern bool CloseHandle(IntPtr hObject); 
    } 

Y esta comprobación rápida es también propenso a condiciones de carrera, a menos que devuelva el manejador de archivo desde allí, y pasarlo al constructor relevante FileStream.

+2

Por alguna razón, las personas nunca parecen ser reconocidas por resolver el problema, solo por responder la pregunta. +1 por responder la pregunta que SE DEBERÍA haber hecho. –

+0

+1. @Ben Voigt: Bueno, no hay forma de que alguien sepa el problema, ya que lo especifiqué, PERO mi pregunta es QUÉ QUISE SABER. De hecho, estoy usando .Exista para verificar si mi aplicación creó una carpeta temporal (que busca una carpeta que no existe y crea una que luego pasa el nombre). Podría intentarlo {Directory.Delete()} catch pero prefiero existir para convencerme. Bajo ninguna circunstancia debe haber nada más que mi aplicación elimine la carpeta. La carpeta se renombra una vez que tuvo éxito. Entonces Leon realmente no resolvió mi problema. –

+1

@Ben Voigt: en realidad estaba equivocado. En ese caso, uso Directory.delete, pero cuando creo el directorio, uso esa línea para verificar si existe, entonces utilizo Directory.CreateDirectory o file.open con el nombre de archivo devuelto. Uso la función para generar el nombre único en un formato específico. –

2

Mi manera de comprobar esto es el uso de la FileSystemInfo, aquí está mi código:

FileSystemInfo info = 
    File.GetAttributes(data.Path).HasFlag(FileAttributes.Directory) ? 
    new DirectoryInfo(data.Path) : (FileSystemInfo)new FileInfo(data.Path); 

return info.Exists; 
+1

File.GetAttributes arroja una System.IO.FileNotFoundException si no existe un archivo ni directorio –