Mi sembra che File.Exists() sia molto più lento quando il file non esiste o l'utente non ha accesso rispetto a quando il file esiste.Perché File.Exists() è molto più lento quando il file non esiste?
è vero?
Questo non ha senso per me.
Mi sembra che File.Exists() sia molto più lento quando il file non esiste o l'utente non ha accesso rispetto a quando il file esiste.Perché File.Exists() è molto più lento quando il file non esiste?
è vero?
Questo non ha senso per me.
Generalmente quando si cerca un sacco di cose per qualcosa, non si può essere sicuri della loro mancanza di esistenza a meno che non si sia cercato tutti i posti possibili che avrebbe potuto essere. Quando si cerca qualcosa (nella maggior parte dei tipi di collezioni) il caso peggiore è quando l'oggetto non esiste nella collezione.
Non ho un benchmarking File.Exists
in particolare ma dubito fortemente che ci sia una differenza davvero notevole in quei casi, a meno che non lo facciate migliaia di volte. Come sei arrivato a questa conclusione?
File.Exists
intercetta le eccezioni. Il sovraccarico di raccolta e acquisizione di un'eccezione può contribuire a prestazioni scadenti.
File.Exists
funziona così:
controllare per vedere se il file esiste, tenta di aprire il file ... se viene generata un'eccezione il file non esiste.
Questo processo è più lento dell'apertura di un file e non viene generata alcuna eccezione (ovvero quando il file esiste).
Grazie. L'avevo notato nella documentazione e mi chiedevo. Probabilmente influisce anche sulle prestazioni. Farei clic sulla freccia su per te ma non ho ancora la reputazione. –
Anche questo è stato il mio primo pensiero. @Sarah, se è davvero un problema, potresti voler tornare a P/Invocare Win32 GetFileAttributes() (che restituisce -1 se il file non è stato trovato). – peterchen
Questo è il problema di File.Exists che tenta di aprire il file. Se un altro thread tenta di accedere al file contemporaneamente (mentre il file viene aperto), diciamo che ci saranno conseguenze sfortunate! – SepehrM
File.Exists
crea inoltre un'istanza di autorizzazione CLR prima di verificare che il file esista per il file. Un'alternativa (anche se non ho provato per le prestazioni) è PathFileExists se si sta facendo un sacco di controlli:
[DllImport("Shlwapi.dll", SetLastError = true, CharSet = CharSet.Auto)]
private extern static bool PathFileExists(StringBuilder path);
void Exists()
{
// A StringBuilder is required for interops calls that use strings
StringBuilder builder = new StringBuilder();
builder.Append(@"C:\test.txt");
bool exists = PathFileExists(builder);
}
Questo è MOLTO più veloce. Ho appena eseguito un test delle prestazioni non isolato su un codice che avevo utilizzato File.Exists. L'ho poi ri-eseguito dopo aver aggiornato la mia implementazione per utilizzare il tuo approccio sopra. Il codice originale (sullo stesso scenario di utilizzo) utilizzava il 5% del tempo di traccia dello stack. Utilizzando questo approccio, tale numero è sceso a circa lo 0,5%. Per il nostro processo che controlla ripetutamente la presenza di file, questo rappresenta un enorme miglioramento. Grazie! –
È sbalorditivo quanto sia più veloce! – BradVoy
Stavo facendo un po 'di tempo con i controlli File.Exists che richiedevano una quantità folle di tempo. Questa soluzione riduce l'elaborazione a una frazione del tempo. – Siewers
file e tutti i suoi metodi tipicamente lavorare con handle di file di Windows.
Se si fanno un sacco di controlli, si dovrebbe usare:
FileInfo fiInfo = new FileInfo(@"c:\donotexists");
if (fiInfo.Exists)
return true;
Invece di lavorare internamente con handle di file, esamina attributi di file ed è molto più veloce. Inoltre, non controlla le eccezioni, che è una grande rallentamento .NET
Sembra che "FileInfo.Exists" alla fine effettui le stesse chiamate di "File.Exists". (Usando Reflector, puoi vedere che deve eseguire 'FillAttributeInfo' e aprire' SafeFindHandle', proprio come 'File.Exists'). –
Ho eseguito il seguente test, e sul mio PC, almeno, i tempi sono circa la stessa:
static void TestExists()
{
Stopwatch sw = Stopwatch.StartNew();
for (int i = 0; i < 1000; i++)
{
if (!File.Exists(@"c:\tmp\tmp" + i.ToString() + ".tmp"))
Console.WriteLine("File does not exist");
}
Console.WriteLine("Total for exists: " + sw.Elapsed);
sw = Stopwatch.StartNew();
for (int i = 0; i < 1000; i++)
{
if (File.Exists(@"c:\tmp\tmp_" + i.ToString() + ".tmp"))
Console.WriteLine("File exists");
}
Console.WriteLine("Total for not exists: " + sw.Elapsed);
}
i risultati sono stati in linea con il seguente (ogni corsa è leggermente diverso, ma circa la stessa):
Total for exists: 00:00:00.0717181
Total for not exists: 00:00:00.0824266
ma attraverso una rete (sulla LAN a un server di un hop di distanza), ho trovato la prova di essere un po 'più lento quando i file sono effettivamente esistiti. L'ho annusato e c'era un solo pacchetto SMB in ogni direzione.
Total for exists: 00:00:02.4028708
Total for not exists: 00:00:00.6910531
Questo test non è molto affidabile perché si misura anche l'output sulla console. – t3chb0t
@ t3chb0t: l'output visualizzato è l'output totale. Non sono riuscito a essere molto chiaro su questo, ma il primo ciclo funzionava con i file esistenti (quindi nessun output da quel loop) e il secondo era per file che non esistevano (quindi nessun output). Quindi i tempi non includevano alcuna uscita della console. I numeri sarebbero stati molto più grandi se avessero incluso 1000 linee di output per console. –
Effettivamente - confronta a "Elenco .Conti". –
Considera un file che esiste ma l'utente non ha accesso ad esso. Il flusso non sarebbe lo stesso di se l'utente avesse? vale a dire: ottenere un puntatore al file e controllare le autorizzazioni? O forse le autorizzazioni impediscono di trovare il file per controllare le autorizzazioni e sembra una lista vuota?o la stessa cosa che stai descrivendo si verifica quando controlli le autorizzazioni? iniziando a dare un senso a me, immagino. Thx –
Sì, le autorizzazioni sono ancora un'altra raccolta da cercare. Se trovi quello che stai cercando, puoi rinunciare immediatamente, mentre per concludere non riesci a trovare quello che stai cercando, dovrai verificare tutte le possibilità. –