0

I have a file that is being written to by another process (completely different pid). I know it is writing to the file line-by-line.

From Java, I would like to read this file line-by-line as the lines are being written to it. (or as close as I can get to that).

Rather than re-inventing the wheel...is there already a common way to achieve this in Java? It would be nice to have a blocking function called .readLine().

Cheetah
  • 13,785
  • 31
  • 106
  • 190
  • 2
    You mean, you want to synchronize the producer and the consumer? Can you modify the sources of the writer, or isn't it under your control? Have you tried with a filesystem-level watcher? What are the supported OS? – Raffaele Sep 24 '14 at 19:28
  • I think this is quite like http://stackoverflow.com/questions/557844/java-io-implementation-of-unix-linux-tail-f - I'd personally prefer the Apache Commons IO way. – sfThomas Sep 24 '14 at 19:33

1 Answers1

1

You can use a WatchService to observe events from your operating system.

I prefer the option using the take method since it prevents your system from polling needlessly and waits for events from your operating system.

I have used this successfully on Windows, Linux and OSX - as long as Java 7 is available since this is a new feature since JDK 1.7.

Here is the solution I came up with - running in a different thread than the main thread since I didn't want this to block my UI - but this is up to you and your application architecture.

boolean run = true;
WatchService watchService = FileSystems.getDefault().newWatchService();
Path watchingPath = Paths.get("path/to/your/directory/to/watch");
watchingPath.register(watchService, StandardWatchEventKinds.ENTRY_CREATE, StandardWatchEventKinds.ENTRY_DELETE, StandardWatchEventKinds.ENTRY_MODIFY);

WatchKey key = null;
while(run && !isCancelled()) {
    try {
        key = watchService.take();
        for(WatchEvent<?> event : key.pollEvents()) {
            if(!isCancelled()) {
                if(event.context().toString().equals(fileName)) {
                    //Your file has changed, do something interesting with it.
                }
            }
        }
    } catch (InterruptedException e) {
        //Failed to watch for result file cahnges
        //you might want to log this.
        run = false;
    } catch (ClosedWatchServiceException e1) {
        run = false;
    }
    
    boolean reset = key.reset();
    if(!reset) {
        run = false;
    }
}

See Also

Community
  • 1
  • 1
blo0p3r
  • 6,790
  • 8
  • 49
  • 68
  • This doesn't answer my question...my question was around the reading of the file....I am making the assumption that I cant read and write to the same file a tame time from different processes - maybe I'm wrong? – Cheetah Sep 25 '14 at 08:15
  • Are you in control of the software that writes the file as well? – blo0p3r Sep 25 '14 at 20:16
  • I am, but I'd rather not add any extra logic if it can be avoided. – Cheetah Sep 26 '14 at 13:17
  • If your file on your "writer" program is closed, after writes, this code above will get called every time there is a line that is written. If you file is ALWAYS open on the writer side, then you will need to change this to a polling function that will re-open the file every now and again and get the new changes (that is using this technique). – blo0p3r Sep 26 '14 at 13:35