While there are 4 other answers, I don't think any address both your points: (1) to print the last 6 lines and (2) then keep monitoring the file and printing new lines.
I also think you should keep it simple to better convey your code's intent and remove bug risk:
- just use a
BufferedReader
rather than RandomAccessFile
- this is what BufferedReader
is for
- instead of using an array just use a FIFO Queue like
ArrayDeque<String>
- this is a perfect use case for it and the "ringbuffer" implementation is fully encapsulated inside ArrayDeque
A barebones implementation which does all this would be something like:
public static void MonitorFile(String filePath)
throws FileNotFoundException, IOException, InterruptedException
{
// Used for demo only: count lines after init to exit function after n new lines
int newLineCount = 0;
// constants
final int INITIAL_LINE_LIMIT = 6;
final int POLLING_INTERVAL = 1000;
// file readers
FileReader file = new FileReader(filePath);
BufferedReader fr = new BufferedReader(file);
// read-and-monitor loop
boolean initialising = true;
Queue<String> lineBuffer = new ArrayDeque<String>(INITIAL_LINE_LIMIT);
int lineCount = 0;
while (true) {
String line= fr.readLine();
if (line != null)
{
if (initialising) { // buffer
lineBuffer.add(line);
if (++lineCount > INITIAL_LINE_LIMIT) lineBuffer.remove();
}
else { // print
System.out.printf("%d %s%n", ++lineCount, line);
newLineCount++;
}
}
else
{
// No more lines, so dump buffer and/or start monitoring
if (initialising)
{
initialising = false;
// reset the line numbers for printing
lineCount = Math.max(0, lineCount - INITIAL_LINE_LIMIT);
// print out the buffered lines
while((line = lineBuffer.poll()) != null)
System.out.printf("%d %s%n", ++lineCount, line);
System.out.println("finished pre-loading file: now monitoring changes");
}
// Wait and try and read again.
if (newLineCount > 2) break; // demo only: terminate after 2 new lines
else Thread.sleep(POLLING_INTERVAL);
}
}
}
Points to consider:
- For what it's worth, I would pass the
BufferedReader
in as a parameter so this becomes more generalised,
- This needs some kind of cancellation so it doesn't monitor forever.
- Rather than polling and sleeping your thread you could also use file change monitoring, but that code would be more complex than is suitable for this answer.
The above code gives the following output
2 test line b
3 test line c
4 test line d
5 test line e
6 test line f
7 test line g
finished pre-loading file: now monitoring changes
8 test line h
9 test line i
10 test line j
11 test line k