Cuando se está copiando un archivo en la carpeta del observador de archivos, ¿cómo puedo identificar si el archivo está completamente copiado y listo para usar? Porque recibo múltiples eventos durante la copia de archivo. (El archivo se copia a través de otro programa usando File.Copy.)FileSystemWatcher: ¿está listo para usar el archivo?
Respuesta
Tuve este problema al escribir un archivo. Recibí eventos antes de que el archivo estuviera completamente escrito y cerrado.
La solución es utilizar un nombre de archivo temporal y renombrar el archivo una vez finalizado. Luego, observe el evento de cambio de nombre del archivo en lugar de la creación del archivo o el evento de cambio.
Nota: este problema no se puede resolver en caso genérico. Sin conocimiento previo sobre el uso de archivos, no se puede saber si otros programas terminaron de funcionar con el archivo.
En su caso particular, debería ser capaz de averiguar en qué operaciones consiste File.Copy.
El archivo de destino más probable está bloqueado durante toda la operación. En este caso, debería poder simplemente intentar abrir el archivo y manejar la excepción de "violación de modo de compartir".
También puede esperar un tiempo ... - opción muy poco confiable, pero si conoce el rango de tamaño de los archivos, es posible que pueda tener un retraso razonable para que Copie termine.
También puede "inventar" algún tipo de sistema de transacción, es decir, crear otro archivo como "nombre_archivo_destino.COPYLOCK" que programa crearía antes de copiar el "nombre_archivo_destino" y eliminarlo posteriormente.
Cuando me encontré con este problema, la mejor solución que se me ocurrió fue tratar continuamente de obtener un bloqueo exclusivo en el archivo; mientras se está escribiendo el archivo, el intento de bloqueo fallará, esencialmente el método en this responder. Una vez que el archivo no se está escribiendo, el bloqueo tendrá éxito.
Desafortunadamente, la única forma de hacerlo es envolviendo/probando la apertura del archivo, lo que me avergüenza: tener que usar try/catch siempre es doloroso. Sin embargo, parece que no hay forma de evitarlo, así que es lo que terminé usando.
Modificación del código en esa respuesta hace el truco, así que terminamos usando algo como esto:
private void WaitForFile(FileInfo file)
{
FileStream stream = null;
bool FileReady = false;
while(!FileReady)
{
try
{
using(stream = file.Open(FileMode.Open, FileAccess.ReadWrite, FileShare.None))
{
FileReady = true;
}
}
catch (IOException)
{
//File isn't ready yet, so we need to keep on waiting until it is.
}
//We'll want to wait a bit between polls, if the file isn't ready.
if(!FileReady) Thread.Sleep(1000);
}
}
Es posible que desee agregar un conteo y dejar de intentar x intentos fallidos. – McGarnagle
Aquí es un método que va a volver a intentar el acceso a archivos hasta un número X de veces, con un Sleep
entre intentos. Si nunca se pone el acceso, la aplicación se mueve en:
private static bool GetIdleFile(string path)
{
var fileIdle = false;
const int MaximumAttemptsAllowed = 30;
var attemptsMade = 0;
while (!fileIdle && attemptsMade <= MaximumAttemptsAllowed)
{
try
{
using (File.Open(path, FileMode.Open, FileAccess.ReadWrite))
{
fileIdle = true;
}
}
catch
{
attemptsMade++;
Thread.Sleep(100);
}
}
return fileIdle;
}
Puede ser utilizado como esto:
private void WatcherOnCreated(object sender, FileSystemEventArgs e)
{
if (GetIdleFile(e.FullPath))
{
// Do something like...
foreach (var line in File.ReadAllLines(e.FullPath))
{
// Do more...
}
}
}
private Stream ReadWhenAvailable(FileInfo finfo, TimeSpan? ts = null) => Task.Run(() =>
{
ts = ts == null ? new TimeSpan(long.MaxValue) : ts;
var start = DateTime.Now;
while (DateTime.Now - start < ts)
{
Thread.Sleep(200);
try
{
return new FileStream(finfo.FullName, FileMode.Open);
}
catch { }
}
return null;
})
.Result;
... por supuesto, puede modificar los aspectos de este para adaptarse a su necesariamente.
- 1. AVPlayerStatus para el archivo local no está listo
- 2. ¿Está listo el nodo.js para producción?
- 3. ¿Está ZeroMQ listo para producción?
- 4. ¿Está Node.js listo para aplicaciones críticas para el negocio?
- 5. ¿Está Pylons listo para la empresa?
- 6. ¿JRuby está listo para la producción?
- 7. ¿Boost :: interprocess está listo para el horario de máxima audiencia?
- 8. Activadores FileSystemWatcher para filestream open
- 9. ¿Cómo verificar si el documento está listo?
- 10. ¿Delphi 2010 está listo para el uso de producción?
- 11. ¿Microsoft StreamInsight está listo para el horario estelar?
- 12. ¿Kafka está listo para el uso de producción?
- 13. ¿Ya está listo el video html5 para horario estelar?
- 14. ¿Está listo/recomendado Pyramid para el horario de máxima audiencia?
- 15. ¿LINQ-to-NHibernate está listo para el código de producción?
- 16. ¿Qué filtro de FileSystemWatcher necesito usar para encontrar nuevos archivos?
- 17. FileSystemWatcher para FTP
- 18. ¿Usar en carga o listo?
- 19. ¿Aún no está G1GC oficialmente listo para producción?
- 20. ¿Hay alguna marco de juego para Android listo para usar
- 21. ¿Hay algún control de mapa listo para usar para wp7?
- 22. ¿XCB está listo para producción? ¿Debo usar Xlib en su lugar?
- 23. FileSystemWatcher para ver la ruta UNC
- 24. ¿Cree que ASP.Net MVC está listo para la producción?
- 25. ¿Está JavaScript listo para visualizar grandes conjuntos de datos?
- 26. ¿Cómo detectar cuando un lienzo está listo para la manipulación?
- 27. Está ASP.NET MVC 3 listo para aplicaciones comerciales
- 28. ¿Cuándo terminará Unladen Swallow "listo" o "listo" para uso real?
- 29. ¿Visual Studio 2010 RC está listo para la producción?
- 30. FileSystemWatcher Network Disconnect
Esto no funciona si alguien más te empuja el archivo (como sobre FTP o algo así) - tienes que saber que el archivo está listo para usar antes de que puedas cambiarle el nombre y decir que está listo para usar :) – Tacroy