java - getpath - ¿Cómo saber cuándo un Archivo está "Hecho" copiando en un Directorio vigilado?
local path java (6)
Cuando se crea una entrada, obtendrá un evento ENTRY_CREATE
. Para cada modificación posterior, obtendrá un evento ENTRY_MODIFY
. Cuando se completa la copia, se te notificará con un ENTRY_MODIFY
.
Estoy usando la API WatchService para mirar un directorio y obtener eventos ENTRY_CREATE cuando un usuario comienza a copiar un archivo en el directorio. Sin embargo, los archivos con los que estoy trabajando pueden ser grandes y me gustaría saber cuándo finaliza la copia. ¿Hay alguna API java incorporada que pueda usar para lograr esto, o lo mejor es solo hacer un seguimiento del tamaño de los archivos creados y comenzar a procesar cuando el tamaño deje de crecer?
EDITAR: Aquí está mi código de ejemplo:
package com.example;
import java.io.File;
import java.nio.file.FileSystems;
import java.nio.file.Path;
import java.nio.file.StandardWatchEventKinds;
import java.nio.file.WatchEvent;
import java.nio.file.WatchKey;
import java.nio.file.WatchService;
public class Monitor {
public static void main(String[] args) {
try {
String path = args[0];
System.out.println(String.format( "Monitoring %s", path ));
WatchService watcher = FileSystems.getDefault().newWatchService();
Path watchPath = FileSystems.getDefault().getPath(path);
watchPath.register(watcher, StandardWatchEventKinds.ENTRY_CREATE, StandardWatchEventKinds.ENTRY_MODIFY);
while (true) {
WatchKey key = watcher.take();
for (WatchEvent<?> event: key.pollEvents()) {
Object context = event.context();
System.out.println( String.format( "Event %s, type %s", context, event.kind() ));
}
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
Que produce esta salida:
Monitoring /Users/ericcobb/Develop/watch
Event .DS_Store, type ENTRY_MODIFY
Event 7795dab5-71b1-4b78-952f-7e15a2f39801-84f3e5daeca9435aa886fbebf7f8bd61_4.mp4, type ENTRY_CREATE
- Creo que la forma más común de lograr esto es copiar el archivo en un directorio temporal en la misma partición y luego moverlo al directorio supervisado mediante un comando de movimiento atómico.
- Quizás una solución también podría lograrse jugando con los archivos de marcas de tiempo
Sin embargo, ambas soluciones deben realizarse en la aplicación de escritura. Creo que no se puede decir con certeza de la aplicación de lectura.
Esta es la biblioteca que usamos hoy:
https://github.com/levelsbeyond/jpoller
Es una bifurcación de un proyecto de código abierto que el autor original ya no mantiene. Hemos arreglado algunos errores y hoy lo usamos en producción.
Funciona al verificar el tamaño de los archivos en un directorio y considera que el archivo está listo (listo para el procesamiento) una vez que el tamaño del archivo deja de crecer durante un período de tiempo.
Tal vez puedas decir tratando de obtener acceso de escritura al archivo, pero esto depende de dos factores y requiere investigación:
- La aplicación de escritura debe adquirir permiso de escritura exclusivo para el archivo y no debe cerrar el archivo antes de que esté completo.
- Debe ser posible probar esto desde Java. Lo probaría si abro el archivo como FileChannel para el acceso ESCRIBIR arroja una excepción si el archivo todavía está bloqueado para escritura por otro programa. Desafortunadamente, el Javadoc no entra en detalles sobre esto.
File file = child.toAbsolutePath().toFile();
if(file.isFile() && file.isWrite())
{
}
tal vez esta sea la forma de descubrir lo que quieres, pero no en la declaración de tiempo.
Funcionará cuando realmente acceda al archivo.
La única opción válida para garantizar, ningún otro proceso está escribiendo en el archivo más es obtener con éxito un bloqueo de escritura en el archivo. Aunque es un poco torpe, puedes usar FileChannel y FileLock para ese fin
try(FileChannel ch = FileChannel.open(p, StandardOpenOption.WRITE);
FileLock lock = ch.tryLock()){
if(lock == null) {
//no lock, other process is still writing
} else {
//you got a lock, other process is done writing
}
} catch (IOException e) {
//something else went wrong
}
También podría obtener un bloqueo usando ch.lock()
que es una llamada de bloqueo. Pero dado que los eventos ENTRY_MODIFY se generan continuamente cuando se escribe el archivo, también puede usar tryLock y esperar el siguiente evento.