Comment utiliser WatchService de Java, j'ai fait une note car il s'adaptait de manière inattendue lorsque j'ai commencé avec une sensation de légèreté. Le code est Kotlin, mais est-ce le même en Java?
class Watcher private constructor(
val path: Path,
val listener: (e: WatchEvent<Path>, target: Path) -> Unit
) : AutoCloseable {
private val executor = Executors.newSingleThreadExecutor()
private val watchService = path.fileSystem.newWatchService()
init {
val watchKey = path.register(watchService, ENTRY_CREATE, ENTRY_DELETE, ENTRY_MODIFY)
executor.submit {
while (true) {
val key = watchService.take()
assert(watchKey == key, { "Une seule clé est enregistrée, elle doit donc toujours correspondre" })
for (e in watchKey.pollEvents()) {
@Suppress("UNCHECKED_CAST") //Chaque fois que l'événement WatchKey est au-dessus, il est garanti qu'il s'agit de Path
listener(
e as WatchEvent<Path>,
path.resolve(e.context())
)
}
val valid = watchKey.reset()
if (!valid) throw RuntimeException("Ne devrait pas arriver normalement")
}
}
}
override fun close() {
executor.shutdownNow()
executor.awaitTermination(1, TimeUnit.SECONDS) //Cette valeur est appropriée
watchService.close()
}
companion object {
fun watch(
path: Path,
listener: (e: WatchEvent<Path>, target: Path) -> Unit
): Watcher {
return Watcher(path, listener)
}
}
}
. Parce que
WatchService.take ()se bloque jusqu'à ce qu'un changement soit détecté.
poll ()ne bloque pas et renvoie
null`, mais dans tous les cas, il est plus pratique de le faire dans un thread séparé.WatchKey.pollEvents ()
renvoie une liste de WatchEvents avec des caractères génériques. Cependant,
WatchEvent.context ()est [Document](https://docs.oracle.com/javase/jp/9/docs/api/java/nio/file/WatchEvent.html#context--) et l'événement Il est garanti de toujours renvoyer
Path tant que l'un des éléments ʻENTRY_CREATE
, ʻENTRY_DELETE, ʻENTRY_MODIFY
. En bref, ce sera toujours Path
, donc il n'y a aucun problème à le lancer sans condition.Path
retourné parWatchEvent.context () ʻest retourné comme chemin relatif depuis le répertoire surveillé. Par conséquent, si vous essayez d'utiliser le chemin retourné tel quel, il essaiera de trouver le fichier en fonction du répertoire actuel. Par conséquent, le fichier est introuvable (sauf si le répertoire de surveillance est en cours) et une exception est déclenchée. Ce comportement est plutôt peu intuitif et peu pratique, il renvoie donc à l'auditeur un
Chemin séparé qui est résolu en fonction du
Chemin` du répertoire surveillé.WatchKey.reset ()
. La valeur de retour indique si la réinitialisation a réussi, mais pour autant que vous lisez Document Cela ressemble presque à ʻis Valid () `. La condition de validité de la clé est
- Annulé explicitement en appelant la méthode cancel
- Annulé implicitement car l'objet n'est plus accessible
- Annulé en fermant le service de surveillance
Donc, ce code ne se produit généralement pas ...
Watcher
?Difficile à utiliser ...
Recommended Posts