Il y a quelques questions de Java semblables à celui-ci mais aucun d'entre eux n'avait accepté des réponses que je pourrais trouver et ma situation est un peu plus spécifique. J'ai un programme qui traite les fichiers un par un lorsqu'ils sont introduits dans un répertoire. Parfois, les fichiers peuvent rester verrouillés en cours d'utilisation par le programme les déposant pendant quelques secondes après qu'ils soient visibles à mon programme. Je n'ai aucun contrôle sur ce programme. Dans mon programme j'ai déjà la gestion des erreurs à récupérer si un fichier est utilisé lorsque mon programme essaie de le lire. Il en résulte que le fichier est entièrement ignoré. Ce que je veux implémenter est un schéma de réessai pour voir si le fichier est déverrouillé après quelques secondes. Dans une autre question ici, j'ai trouvé une suggestion pour utiliser FileUtils.touch()
. C'est pratique car j'utilise déjà FileUtils dans mon projet. Selon le javadoc, FileUtils.touch()
avec jeter un IOException
si le fichier est utilisé par un autre processus. Super. Cependant, l'un des commentaires de la réponse que j'ai mentionnée mettait en garde contre une condition de concurrence sans aucune explication. Voici le code que je considère la mise en œuvre:En attente de la libération de fichiers
// Implementing Sason's suggestion
int retries = 0;
while (retries < MAX_RETRIES) {
try {
processFile(file);
} catch (IOException ioe) {
// Assumes this is a file in use exception... bad thing?
log.warn("File is in use. Waiting 1 second to retry.");
retries++;
try {
Thread.sleep(1000);
} catch (InterruptedException ie) {
log.warn("Thread interrupted while waiting for file lock to clear.");
break;
}
}
}
Je me rends compte que le fichier pourrait devenir à nouveau verrouillés entre le FileUtils.touch() et l'appel de méthode processFile()
(et je suppose que c'est la condition de course mis en garde contre en la réponse non acceptée j'ai trouvé) mais c'est bien. La méthode processFile()
gère simplement l'erreur de verrouillage comme c'est le cas actuellement. Pour être clair, dans ce cas, il est parfaitement possible que le fichier soit ouvert par un autre processus, mais il ne peut pas être verrouillé.
En outre, alors que parfois le fichier est déverrouillé après une seconde ou deux, dans certains cas, le programme supprimant les fichiers conserve le verrou indéfiniment. J'ai également besoin d'éviter infiniment d'essayer de retraiter le même fichier ainsi que d'être capable d'informer l'expéditeur lorsqu'un fichier ne peut pas être traité après que les tentatives aient été épuisées.
Alors, est-ce qu'il me manque quelque chose ici? Y a-t-il un moyen meilleur/plus sûr de le faire?
Il ne semble pas que 'touch()' soit un moyen fiable de tester si le fichier est ouvert. Il peut fonctionner sur un système particulier avec un processus particulier d'écriture du fichier, et c'est bien, mais si vous exécutez le code ailleurs ou si vous changez d'éditeur, vous devrez effectuer un nouveau test pour vous assurer qu'il fonctionne toujours. La bonne façon de le faire est avec un 'FileLock', mais cela nécessite que le programme d'écriture utilise le mécanisme de verrouillage du système de fichiers sous-jacent. – erickson
J'aurais dû être plus clair dans ma question. C'est correct si le fichier est ouvert dans un autre processus qui n'a pas le fichier verrouillé (comme, par exemple, NotePad ++). Il ne peut simplement pas être verrouillé car 'processFile()' tentera de verrouiller le fichier. Je vois ce que vous pensez de 'FileLock', mais vous avez raison: cela nécessiterait beaucoup de refactoring. Je pense que 'touch()' fonctionnera sur plusieurs plates-formes avec la même mise en garde qu'un autre programme pourrait avoir le fichier ouvert mais pas verrouillé. –