java - Le processus ne peut pas accéder au fichier car ce fichier est utilisé par un autre processus
J'ai un morceau de code qui surveille un répertoire pour l'ajout de fichiers. Chaque fois qu'un nouveau fichier est ajouté à l'annuaire, le contenu du fichier sont repris et publié sur kafka, puis le fichier est supprimé.
Cela fonctionne quand je fais une seule requête, mais dès que j'ai soumis mon code à 5 ou 10 demande de l'utilisateur à partir de jMeter, le contenu est publié sur kafka avec succès, mais le code n'est pas en mesure de supprimer le fichier. Je reçois un FileSystemException
avec un message qui The process cannot access the file because it is being used by another process.
.
Je pense qu'il y a quelques problème de concurrence qui je suis incapable de voir.
public void monitor() throws IOException, InterruptedException {
Path faxFolder = Paths.get(TEMP_FILE_LOCATION);
WatchService watchService = FileSystems.getDefault().newWatchService();
faxFolder.register(watchService, StandardWatchEventKinds.ENTRY_CREATE);
boolean valid = true;
do {
WatchKey watchKey = watchService.take();
for (WatchEvent<?> event : watchKey.pollEvents()) {
if (StandardWatchEventKinds.ENTRY_CREATE.equals(event.kind())) {
String fileName = event.context().toString();
publishToKafka(new File(TEMP_FILE_LOCATION + fileName).toPath(), "topic");
}
}
valid = watchKey.reset();
} while (valid);
}
private void publishToKafka(Path path, String topic) {
try (BufferedReader reader = Files.newBufferedReader(path)) {
String input = null;
while ((input = reader.readLine()) != null) {
kafkaProducer.publishMessageOnTopic(input, topic);
}
} catch (IOException e) {
LOG.error("Could not read buffered file to send message on kafka.", e);
} finally {
try {
Files.deleteIfExists(path); //This is where I get the exception
} catch (IOException e) {
LOG.error("Problem in deleting the buffered file {}.", path.getFileName(), e);
}
}
}
Exception Du Journal :
java.nio.file.FileSystemException: D:\upload\notif-1479974962595.csv: The process cannot access the file because it is being used by another process.
at sun.nio.fs.WindowsException.translateToIOException(Unknown Source)
at sun.nio.fs.WindowsException.rethrowAsIOException(Unknown Source)
at sun.nio.fs.WindowsException.rethrowAsIOException(Unknown Source)
at sun.nio.fs.WindowsFileSystemProvider.implDelete(Unknown Source)
at sun.nio.fs.AbstractFileSystemProvider.deleteIfExists(Unknown Source)
at java.nio.file.Files.deleteIfExists(Unknown Source)
at com.panasonic.mdw.core.utils.MonitorDirectory$FileContentPublisher.publishToKafka(MonitorDirectory.java:193)
at com.panasonic.mdw.core.utils.MonitorDirectory$FileContentPublisher.sendData(MonitorDirectory.java:125)
at com.panasonic.mdw.core.utils.MonitorDirectory$FileContentPublisher.run(MonitorDirectory.java:113)
at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)
Par ailleurs, la WatchService est fermer, donc de mettre
newWatchService()
à l'intérieur d'un try-with-resources. Aussi, puisque vous êtes à l'aide de nio partout ailleurs, pour plus de cohérence au lieu de new File(...).toPath()
ne faxFolder.resolve(filename)
.Kyriacou: depuis le
WatchEvent
’contexte est déjà un Path
lorsque vous regardez un système de fichiers, même la conversion en chaîne de caractères est obsolète et faxFolder.resolve((Path)event.context())
est suffisant. Je pense que vous avez raison, en réaction à la création de l'événement immédiatement, ça ne donne pas le créateur de suffisamment de temps pour fermer le fichier. Il est intéressant de noter, sur mon système, qui a l'effet inverse: la lecture du fichier échoue car il n'est pas encore écrite, mais la suppression des œuvres, comme le système reporte la suppression effective de à la point de, le créateur ferme le fichier.les bons points. Je pense (je besoin de le tester) que lorsqu'un nouveau fichier est créé, vous obtenez deux événements: d'abord, l'entrée de création, suivi par une entrée de modification (lorsque l'horodatage est mis à jour à la clôture du dossier). Le fichier ne doit être lu après l'événement de modification. (Et peut-être qu'après un délai d'attente, dans le cas d'un fichier vide est créé et à gauche.)
Kyriacou: il peut y avoir plus d'un événement de modification pendant que l'autre application est l'écriture dans le fichier. Donc, vous avez à l'installation d'une minuterie qui initie votre action un certain temps après la dernière modification de l'événement, la réinitialisation de la minuterie sur chaque modification. Et c'est encore seulement le traitement de l'affaire que l'autre application crée le fichier, écrit et il se ferme tout droit-forwardly...
OriginalL'auteur Furquan Ahmed | 2016-11-24
Vous devez vous connecter pour publier un commentaire.
En regardant ton code, il semble quand un fichier est choisi par le thread pour la publication de nouveau un autre thread est de la ramasser pour la publication. C'est pourquoi personne n'est capable de le supprimer.
Il faut problème de concurrence. Vous devriez refonte du code basé sur le critère : les étapes qui peut être exécuté en même temps et ceux qui ne peuvent pas l'être.
Si les étapes dans le processus sont :
Aussi le moment où un fichier est sélectionné, vous pouvez le lire dans le buffer , supprimer et ensuite continuer avec de la publication. Cela permettra de s'assurer que le thread principal ne peut pas attribuer ce fichier à un autre thread.
OriginalL'auteur grsdev7
J'ai eu le même problème ainsi que dans le fil de discussion suivant: Le Multithreading sur la File d'attente
lorsque vous essayez de charger un de créer dynamiquement des fichiers à un service de File d'attente et il fallait 2 jours pour moi à résoudre. Grâce à Holger qui ont donné la réponse que ci-dessus selon lequel le verrouillage se produit peut-être en raison de la création n'a pas entièrement fait à la lecture par un autre thread, il m'a sauvé beaucoup de temps.
Ma première solution qu'a trouvé un grand nombre de l'internet, a été:
Je l'ai changé pour:
Et tout fonctionne parfaitement. Gérer les "en quelque sorte" plusieurs ENTRY_MODIFY événements de tir (copiés les fichiers téléchargés), j'ai effectuer la suppression dans le fichier à l'intérieur de la uploadToQueue() la méthode une fois qu'il est téléchargé.
J'espère que mon approche fondée sur la contribution ci-dessus sera également aider les autres avec le même problème.
OriginalL'auteur I Made Putrama
Vous devez fermer toutes les connexions qui accède à ce fichier avant de le supprimer.
try-with-resources
fait que, avant l'exécution de lafinally
code.C'est problème de concurrence
OriginalL'auteur Arun Kasyakar