2010-04-03 20 views
38

Mi trovo molto a fare questo solo per assicurarmi che il nome del file non sia in uso. C'è un modo migliore?Verifica se esiste un file/directory: c'è un modo migliore?

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

E ciò che è sbagliato in questo? Come può essere più facile o più pulito? –

+0

Lo faccio ovunque .... è brutto. Di solito non mi preoccupo della precedenza ma potrebbe succedere –

+0

Perché hai bisogno di questi 2 controlli? Perché non usi solo File.Exists (nome)? – Egor4eg

risposta

51

Certo :)

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

Metodo di estensione per la classe Path? "Esegue operazioni su istanze String che contengono informazioni sul percorso di file o directory." – si618

+0

Si. buona idea per averla in un'istanza di stringa. è davvero pessimo. NET non consente di estendere una classe statica :( –

+0

qualcuno preavviso, errore previsto? .xD 2014ppl da qui, ma ancora grazie @PaulG. – Elegiac

4

penso che sia l'unico modo. Generalmente ho una classe "FileManager" che ha metodi statici che incapsulano i metodi di I/O compresi quelli che hai indicato e poi li usano come "FileManager" su tutte le applicazioni come una libreria.

5

Un altro modo per verificare se il file esiste.

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

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

Dubito del motivo per cui scenderò il voto per questa risposta? – Anonymous

+0

Guarda i tag prima di pubblicare una risposta: – lsalamon

+5

Il tag è C#, .NET e file. Questo è il codice C# e può restituire il valore desiderato tput. – Anonymous

29

Nota che il fatto che si sta utilizzando esiste() per verificare la presenza di file o directory nome in uso è soggetto a condizioni di gara.

In qualsiasi momento dopo il test Exists(), è possibile che sia stato creato un file con quel nome prima che il codice raggiunga il punto in cui si crea un file, ad esempio.

(suppongo che sia una condizione eccezionale per il file già esistente).

È più semplice aprire semplicemente il file, specificando un parametro FileShare appropriato.

Esempio:

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 
     } 
    } 
} 

Così semplicemente gestire la IOException in caso di fallimento potrebbe causare codice più semplice meno soggetto a condizioni di gara, perché ora:

  • Se qualcosa ha già creato il file , FileMode.CreateNew causerà il lancio di IOException
  • Se l'apertura e la creazione hanno esito positivo, a causa di FileShare.None, nessun altro processo può accedere al file finché non lo si chiude.

Purtroppo, non è possibile verificare se un file è attualmente in uso, e non un'eccezione, senza qualche brutta 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); 
    } 

E questo controllo veloce è anche soggetto a condizioni di gara, a meno che non si restituisca l'handle del file da esso e lo si passi al relativo costruttore FileStream.

+2

Per qualche motivo la gente non sembra mai essere riconosciuta per risolvere il problema, solo per rispondere alla domanda. +1 per rispondere alla domanda che DOVREBBE essere stato chiesto. –

+0

+1. @ Ben Voigt: Beh, non c'è modo per nessuno di conoscere il problema da quando l'ho specificato, ma la mia domanda è COSA VOLEVO SAPERE. In realtà sto usando. Esista per verificare se la mia app ha creato una cartella temporanea (che cerca una cartella inesistente e ne crea una quindi passa il nome). Potrei semplicemente provare {Directory.Delete()} ma io preferisco esistere per convincere. In nessuna circostanza, nulla di diverso dalla mia app può eliminare la cartella. La cartella viene rinominata una volta riuscita. Quindi Leon in realtà non ha risolto il mio problema. –

+1

@Ben Voigt: in realtà mi sbagliavo. In tal caso, utilizzo Directory.delete ma quando creo la directory, utilizzo quella riga per verificare se esiste, quindi utilizzo Directory.CreateDirectory o file.open con il nome file restituito. Io uso la funzione per generare il nome univoco in un formato specifico. –

2

Il mio modo di controllare questo sta usando il FileSystemInfo, qui è il mio codice:

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

return info.Exists; 
+1

File.GetAttributes genera un System.IO.FileNotFoundException se non esiste né un file né una directory –

Problemi correlati