2010-02-08 15 views

Respuesta

10

En general, cuando busca un montón de cosas para algo, no puede estar seguro de su falta de existencia a menos que haya buscado todos los lugares posibles que podría haber sido. Al buscar algo (en la mayoría de los tipos de colecciones), el peor caso es cuando el artículo no existe en la colección.

No he evaluado File.Exists en particular, pero dudo mucho que haya una diferencia realmente notable en esos casos a menos que lo haga miles de veces. ¿Cómo llegaste a esta conclusión?

+0

Indeed - comparar con la 'Lista .Contains'. –

+0

Considere un archivo que existe pero el usuario no tiene acceso a él. ¿No sería el flujo igual que si el usuario tuviera? es decir: obtener un puntero al archivo y comprobar los permisos? ¿O tal vez los permisos impiden encontrar el archivo para comprobar los permisos y parece una lista vacía?o lo mismo que está describiendo se produce al verificar los permisos? empezando a tener un poco de sentido, supongo. Thx –

+0

Sí, los permisos son otra colección más para buscar. Si encuentra lo que está buscando, puede darse por vencido inmediatamente, mientras que para concluir que no puede encontrar lo que está buscando, tendrá que marcar todas las posibilidades. –

39

File.Exists está atrapando excepciones. La sobrecarga de subir y capturar una excepción puede contribuir a un rendimiento deficiente.

File.Exists funciona así:

comprobar para ver si el archivo existe, se trata de abrir el archivo ... si se produce una excepción en el archivo no existe.

Ese proceso es más lento que abrir un archivo y no se lanza ninguna excepción (que es cuando existe el archivo).

+0

Gracias. Me di cuenta de eso en la documentación y me pregunté. Probablemente también afecte el rendimiento. Haría clic en la flecha hacia arriba pero aún no tengo la reputación que parece. –

+0

Ese fue mi primer pensamiento, también. @Sarah, si realmente es un problema, puede recurrir a P/Invocar Win32 GetFileAttributes() (que devuelve -1 si no se encuentra el archivo). – peterchen

+0

Ese es el problema de File.Exists tratando de abrir el archivo. Si otro hilo intenta acceder al archivo al mismo tiempo (mientras se abre el archivo), digamos que habrá consecuencias desafortunadas. – SepehrM

28

File.Exists también ejemplifica la autorización de CLR antes de comprobar que el archivo existe para el archivo. Una alternativa (aunque no lo he probado para el rendimiento) es PathFileExists si está haciendo una gran cantidad de cheques:

[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); 
} 
+4

Esto es MUCHO más rápido. Acabo de ejecutar una prueba de rendimiento no aislada en algún código que tenía que estaba utilizando File.Exists. Luego volví a ejecutarlo después de actualizar mi implementación para utilizar su enfoque anterior. El código original (en el mismo escenario de uso) estaba tomando el 5% del tiempo de seguimiento de la pila. Usando este enfoque, ese número cayó a aproximadamente 0.5%. Para nuestro proceso que verifica la existencia de archivos repetidamente, esto representa una gran mejora. ¡Gracias! –

+0

¡Es asombroso cuánto más rápido es esto! – BradVoy

+0

Estaba haciendo una gran cantidad de comprobaciones File.Exists que me tomaron una gran cantidad de tiempo. Esta solución reduce el procesamiento a una fracción del tiempo. – Siewers

-4

de archivos y todos sus métodos suelen trabajar con identificadores de archivos de Windows.

Si usted hace un montón de cheques, usted debe utilizar:

FileInfo fiInfo = new FileInfo(@"c:\donotexists"); 
if (fiInfo.Exists) 
    return true; 

En lugar de trabajar internamente con identificadores de archivo, se ve en atributos de archivo y es mucho más rápido. Además, no comprueba excepciones, que es una gran desaceleración en .NET

+1

Parece que 'FileInfo.Exists' en última instancia realiza las mismas llamadas que' File.Exists'. (Usando Reflector, puede ver que tiene que ejecutar 'FillAttributeInfo' y abrir' SafeFindHandle', al igual que 'File.Exists'). –

3

que corrió la prueba siguiente, y en mi PC, al menos, los tiempos son casi lo mismo:

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

los resultados fueron en la línea de lo siguiente (cada ejecución es ligeramente diferente, pero casi el mismo):

Total for exists: 00:00:00.0717181 
Total for not exists: 00:00:00.0824266 

pero través de una red (en la LAN a un servidor de un salto de distancia), encontré que la prueba sea un poco más lento cuando los archivos realmente existieron. Lo olí y solo había un paquete SMB en cada dirección.

Total for exists: 00:00:02.4028708 
Total for not exists: 00:00:00.6910531 
+1

Esta prueba no es muy confiable porque también mides la salida a la consola. – t3chb0t

+0

@ t3chb0t: La salida que se muestra es la salida total. No fui muy claro al respecto, pero el primer bucle se ejecutó con los archivos existentes (por lo que no se obtuvieron resultados de ese bucle) y el segundo fue para los archivos que no existían (y por lo tanto no hubo salida). Entonces el tiempo no incluyó ninguna salida de consola. Los números habrían sido mucho más grandes si hubieran incluido 1000 líneas de salida de consola. –

Cuestiones relacionadas