13

I am using watchKey to listen for a file change in a particular folder.

Path _directotyToWatch = Paths.get("E:/Raja");
WatchService watcherSvc = FileSystems.getDefault().newWatchService();
WatchKey watchKey = _directotyToWatch.register(watcherSvc, ENTRY_CREATE, ENTRY_DELETE, ENTRY_MODIFY);

while (true) {
    watchKey=watcherSvc.take();
    for (WatchEvent<?> event: watchKey.pollEvents()) {
        WatchEvent<Path> watchEvent = castEvent(event);
        System.out.println(event.kind().name().toString() + " " + _directotyToWatch.resolve(watchEvent.context()));
        watchKey.reset();
    }
}


It working fine for me. If I modify a file in raja folder it gives me the file name with path. But, when I put some files in subfolders like "E:/Raja/Test", it gives me only the path where I put it, not the file name.

How to get the file name?

informatik01
  • 16,038
  • 10
  • 74
  • 104
Raja
  • 239
  • 1
  • 5
  • 18
  • 2
    this is a duplicate of http://stackoverflow.com/questions/5608234/how-can-i-watch-subdirectory-for-changes-with-watch-service-java – Robert H May 17 '13 at 15:34

3 Answers3

20

The reason why you're not getting the file name created/modified inside a subfolder is given by Stephen C in his answer.

Here is a simple example of how to register directories and subdirectories to watch them for the events you are interested in:

/**
 * Register the given directory and all its sub-directories with the WatchService.
 */
private void registerAll(final Path start) throws IOException {
    // register directory and sub-directories
    Files.walkFileTree(start, new SimpleFileVisitor<Path>() {

        @Override
        public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs)
                throws IOException {
            dir.register(watcher, ENTRY_CREATE, ENTRY_DELETE, ENTRY_MODIFY);
            return FileVisitResult.CONTINUE;
        }

    });

}

Check out the official Java Tutorials: Watching a Directory for Changes. There you can find very nice explanations and examples with the source code.

Particularly you'll be interested in this example of how to watch a directory (or directory tree) for changes to files: WatchDir.java.

The method I supplied above was taken from this example (omitting some parts for brevity).
Read the tutorial for the details.

informatik01
  • 16,038
  • 10
  • 74
  • 104
  • I tested the above code and it gives NULL Pointer exception on OpenJDK 11. But OpenJDK has closed this as not an issue mentioning that we can't pass null in constructors. https://bugs.openjdk.java.net/browse/JDK-8133521 – Anil Jun 17 '21 at 03:27
  • @Anil If you look at the source code of the [`java.nio.file.Paths`](https://github.com/openjdk/jdk/blob/master/src/java.base/share/classes/java/nio/file/Paths.java#L97) class you will see, that the `get(URI uri)` method calls [`java.nio.file.Path.of(uri)`](https://github.com/openjdk/jdk/blob/master/src/java.base/share/classes/java/nio/file/Path.java#L196) static method, inside which there is no check for `null` and the `uri` is immediately used to call `getScheme()` on it. So no wonder that if `uri` was `null`, it will result in NPE. But it's totally unrelated to the OP's question. – informatik01 Jun 17 '21 at 06:07
10

The reason you are only seeing an event for "E:/Raja/Test" and not "E:/Raja/Test/Foo.txt" (for example) is that you've only registered the "E:/Raja" directory with the service. This means you will see events on the directory and its immediate members. The "E:/Raja/Test" is a member of the directory, and you are getting events to say that is has been changed ... when files are added to it.

The solution is to register all of subdirectories of "E:/Raja" as well ... going as far down the directory hierarchy as you need to go.

Stephen C
  • 698,415
  • 94
  • 811
  • 1,216
  • 1
    If he registers E:/Raha and E:/Raha/Test I think he will get two events fired if E:/Raja/Test/Foo.txt is created. – Nick May 17 '13 at 17:14
  • 4
    Yes he will. But that's not the point. The point is that the event from the watcher on E:/Raha/Test will give him a CREATE event the full pathname of the created file, but the other one will be a MODIFY event giving the pathname of the directory that was modified. (OK ... I'm going from memory ...) – Stephen C May 18 '13 at 02:28
0

I know this is ugly, hopefully somebody has a better answer but you can create a list of every file in every subfolder and there last modified times.

When you receive ENTRY_CREATE or ENTRY_DELETE compare the folder to your list to figure out which file was changed

When you receive a ENTRY_MODIFY compare the last modified times.

Remember to update your list.

Matthieu
  • 2,736
  • 4
  • 57
  • 87
Nick
  • 3,217
  • 5
  • 30
  • 42
  • 3
    Solution 2 is like saying to your 5 year old to learn how to skateboard because he can't ride a bike. Hardly a solution as both require learning. – Robert H May 17 '13 at 15:33
  • No solution 2 is like saying to your 5 year old to lean how to ride a skateboard because he wants a bike with 4 wheels, that he can fit in his book bag, ride in a standing position and store in his school locker. I've done filewatchers in java and C#. C# simply does it better – Nick May 17 '13 at 15:48
  • 4
    Maybe C# does it better, but the OP maybe need to work with Java, so using C# would not be a solution. I think it's a suggestion rather than a solution. – Marc-Andre May 17 '13 at 16:43
  • I agree it should have been a sugestion I changed it. – Nick May 17 '13 at 17:04
  • C# should not be a suggestion as the question is specifically about Java. A comment, at best... – Matthieu Jul 28 '19 at 04:30