问题
implement a java file watcher which is equivalent to tail -f somefile
I've read a few similar questions. and I've seen a few options.
using
BufferedReader, basic idea is to use buffered reader to read from the file. if null is returned then sleep a few seconds and then continue in a infinite loop. I experimented a bit on this, my result show as long as you read to the end of the file, thengetLinemethod will no longer give you any updates. so does this approach work at all?using
random access file. every time making a read operation, create a random access file and compare the file length with historical one, if current one is longer, then seek to last read and read in the delta parts. I'm sure this works, but with a new random access file opened each time read, isn't there a more efficient approach ?I've seen the new JDK added
streamAPI into buffered file reader, I guess this has nothing to do with the new content appended at the tail. it's only related what was first given. my question is could this stream api be extended to take thetailer functioninto consideration ?
Questions:
can
BufferedReaderbe used to implementtail -f? in my case, once I read pass EOF, only null is returned.can JDK8
streambe used to implementtail -f?is there more efficient implementation other than repeatedly open close file like apache common lib?
回答1:
I eventually used some Apache library to fix this. (will update once I remember it).
essentially the file watchers are file system API dependent. on linux distributions, read over EOF would probably be fine and bring new contents that appended later.
the issue I observed is on MACOs, where once you read after EOF that file handler is no longer valid. you have to reopen the file if you know you are reading new content.
- this was on MacOs Maveriks and I didn't test it's still the same on latest versions.
- also this was based on the JDK api, not underlying MACOS file system API. because I felt
less /Ftail -fshould have been implemented more efficiently.
回答2:
I did this a while ago and from my experience I'd guess that your question may be moot--it might be better to close the file between reads or use the Apache Tailer class as someone suggested from my similar question:
How can I follow a file like "Tail -f" does in Java without holding the file open (Prevent rename/delete)
This helps not only because it helps you refresh but it keeps the file from being locked while you are reading it.
I ended up not using it (because getting software approved in my environment is challenging)--instead I chose to use a process like this:
Detect Change
Open file
Seek to previous position
Read to end of file
Remember position for next seek
Close
This preforms very well and solves quite a few problems--I've been using it for a while now.
Someone in that linked question suggested using java.nio.file.WatchService.poll() to detect changes which works--but so does repeatedly reading the file size.
You mentioned this open/seek/close method in #2--don't worry about performance because the open/tail/close part is going to be very little time compared to waiting for the file to be updated. If you want more efficiency, add a longer delay between file size tests. It will chunk out more lines at a time that way but read the file less often.
Reviewing my code I ended up using a FileChannel (FileInputStream.getChannel()) which has a position setting method.
来源:https://stackoverflow.com/questions/37442784/java-file-tailer-implementation