2009-10-21 18 views
28

he visto varias sugerencias sobre los nombres de archivos de forma aleatoria, incluyendo el uso deC#: ¿Cuál es la forma más rápida de generar un nombre de archivo único?

System.IO.Path.GetRandomFileName() 

o utilizando un

System.Guid 

y añadiendo una extensión de archivo.

Mi pregunta es: ¿Cuál es la forma más rápida de generar un nombre de archivo único?

+37

¿Por qué no utiliza una forma * suficientemente rápida *? – Joren

+1

Una excelente pregunta. La respuesta es que estoy tratando de exprimir cada onza de rendimiento de esta aplicación de sistema de archivos intensivo. –

+4

Esto realmente depende de lo que quiere decir con "único": ¿es universalmente único, único dentro de un sistema de archivos, único entre diferentes hilos en el mismo programa ...? –

Respuesta

36

Un GUID sería extremadamente rápido, ya que su implementación garantiza que Windows puede generar al menos 16,384 GUIDS en un intervalo de 100 nanosegundos de . (Como otros señalaron, la especificación no garantiza, solo permite. Sin embargo, la generación de GUID es realmente muy rápida. Realmente). La probabilidad de colisión en cualquier sistema de archivos en cualquier lugar de cualquier red es muy baja. Es lo suficientemente seguro que, aunque sería una buena práctica comprobar siempre si ese nombre de archivo está disponible de todos modos, en realidad ni siquiera necesitarías hacerlo.

Por lo tanto, no está viendo ninguna operación de E/S excepto la de guardar, y < 0.2 milisegundos (en una máquina de prueba) para generar el nombre. Muy rápido.

+2

¡GUAU! ¿Tiene una fuente de enlace que describa esta garantía de implementación? –

+7

No creo que Windows garantice que ** genere ** 16,384 GUIDS en 100 nS, solo que los valores producidos por el algoritmo GUID están garantizados para tener ese nivel de distribución. Además, usando lógica, 16k GUIDS por 100-Ns sería 163 billones de GUIDS por segundo ... ¿lo que significa que se necesita menos de 1/10 de un ciclo de CPU para producir un GUID? Eso no tiene mucho sentido. – LBushkin

+0

vea esta pregunta sobre la singularidad de GUID http://stackoverflow.com/questions/39771/is-a-guid-unique-100-of-the-time – BlackTigerX

3

Si controla el destino donde se ubicarán los archivos, y solo hay un proceso y una secuencia de comandos que le escriben, solo agregue un número de incremento automático a un nombre base.

Si no controla el destino, o necesita una implementación multiproceso, use un GUID.

+1

Aunque casi siempre uso GUID para este problema, LBushkin tiene razón sobre el rendimiento. Si realmente desea * cada * gota de ejecución, incrementar un número entero y convertirlo en una cadena es más rápido que generar un Guid y convertirlo en una cadena ... Pero solo funcionará si tiene el control del directorio. –

17

¿Quieres System.IO.Path.GetTempFileName()

realidad no puedo decir si es más rápido o no, pero es la derecha manera de hacer esto, lo que es más importante.

+0

+1 - esta es la solución más simple y mejor. – Noldorin

+31

Eso realmente crea un archivo. Creo que te refieres a System.IO.Path.GetRandomFileName() –

+1

Dan es correcto. Crea un archivo en el directorio temporal de Windows. – adrianbanks

0

Use un Int e increméntelo para cada archivo.

+2

OP quería un nombre de archivo único ... entonces, ¿qué ocurre si un archivo llamado (por ejemplo) '" 1 "' ya existe? – Sree

-1

algo como:

file.MoveTo(deletedfilesdir + @"\" + f.Name + **DateTime.Now.ToFileTimeUtc()** + f.Extension); 
1

Si controlas el directorio, puede nombrar a su archivo basado en el LastWriteTime:

DirectoryInfo info = new DirectoryInfo(directoryPath); 
long uniqueKey = info.LastWriteTime.Ticks+1L; 
string filename = String.Format("file{0}.txt", key); 

Pero hay que vigilar los espectáculos de este código: supongo que la construcción un DirectoryInfo no es gratis.

+0

"crear un DirectoryInfo no es gratis" - Sospecho que es correcto, especialmente si el disco/directorio no es local para la computadora (unidad de red/NAS/etc.) –

5

Bueno, he estado escribiendo controladores de sistema de archivos durante 20 años y diría que Rex es correcto. Generar un guid es mucho más rápido, ya que requiere mucha menos sobrecarga que buscar un nombre de archivo único. GetTempFileName realmente crea un archivo, lo que significa que tiene que llamar a toda la pila de controladores del sistema de archivos (quién sabe cuántas llamadas serían y un cambio al modo kernel). GetRandomFileName parece que es más rápido, sin embargo, confiaría en la llamada GUID para ser aún más rápido. Lo que las personas no se dan cuenta es que incluso las pruebas de la existencia de un archivo requieren una llamada completa a través de la pila del controlador. En realidad resulta en un abrir, obtener atributos y cerrar (que son al menos 3 llamadas, dependiendo del nivel). En realidad, es un mínimo de 20 llamadas a funciones y una transición al modo kernel. La garantía de GUIDS de singularidad es lo suficientemente buena para la mayoría de los propósitos.

Mi recomendación es generar el nombre y crear el archivo solo si no existe. Si lo hace, lanza una excepción y captúrala, luego genera un nuevo guid y vuelve a intentarlo. De esta forma, tienes cero posibilidades de errores y puedes dormir tranquilo por la noche.

En una nota lateral, la verificación de errores es tan exagerada. El código debe diseñarse para que se bloquee si las suposiciones son incorrectas, o detectar excepciones y tratarlas en ese momento. Es mucho más rápido pulsar y abrir y direccionar en la pila de excepciones, que comprobar cada error en cada función.

0

Espero que esta función auto iterativa ayude a alguien a generar un nombre de archivo único.

public string getUniqueFileName(int i, string fullpath, string filename) 
{ 
    string lstDir = fullpath.Substring(0, fullpath.LastIndexOf('\\')); 
    string name = Path.GetFileName(fullpath); 
    string path = fullpath; 

    if (name != filename) 
     path = Path.Combine(lstDir, filename); 

    if (System.IO.File.Exists(path)) 
    { 
     string ext = Path.GetExtension(name); 
     name = Path.GetFileNameWithoutExtension(name);     
     i++; 
     filename = getUniqueFileName(i, fullpath, name + "_" + i + ext); 
    } 

    return filename; 
} 
+0

¿No crearía esto nombres del formulario 'file_1_2_3 ¿? – user5226582

+0

Si bien esto genera un nombre de archivo único en la ruta (aunque no es seguro para subprocesos) será muy lento en comparación con otros métodos que simplemente generan un nombre de archivo único sin verificar si ya existe. Supongo que el operador necesita una generación rápida de un nombre de archivo único. Por cierto, su respuesta resuelve el problema y podría ser útil para otros. – Perrier

+0

sí, lo hace. Mi expectativa era hacer un incremento en el mismo número, pero se convirtió en concatenar. Necesita modificar el código para que funcione como se esperaba. Estaría agradecido si alguien corrige mi código. Gracias por adelantado. – Bikuz

Cuestiones relacionadas