Вопрос-ответ

Java IO implementation of unix/linux "tail -f"

Реализация Java IO для unix / linux "tail -f"

Мне интересно, какие методы и / или библиотеку использовать для реализации функциональности команды Linux "tail -f". По сути, я ищу дополнение / замену для java.io.FileReader. Клиентский код может выглядеть примерно так:

TailFileReader lft = new TailFileReader("application.log");
BufferedReader br = new BufferedReader(lft);
String line;
try {
while (true) {
line= br.readLine();
// do something interesting with line
}
} catch (IOException e) {
// barf
}

Недостающая часть является разумной реализацией TailFileReader. Он должен иметь возможность считывать части файла, которые существовали до открытия файла, а также добавленные строки.

Переведено автоматически
Ответ 1

Взгляните на реализацию класса Tailer на Apache Commons. Похоже, он также обрабатывает ротацию журналов.

Ответ 2

Возможность продолжить чтение файла и подождать, пока в файле появятся дополнительные обновления для вас, не должна быть такой сложной для выполнения в коде самостоятельно. Вот несколько псевдокодов:

BufferedReader br = new BufferedReader(...);
String line;
while (keepReading) {
line = reader.readLine();
if (line == null) {
//wait until there is more of the file for us to read
Thread.sleep(1000);
}
else {
//do something interesting with the line
}
}

Я бы предположил, что вы хотели бы поместить этот тип функциональности в отдельный поток, чтобы вы могли использовать его в режиме ожидания и не затрагивать какие-либо другие области вашего приложения. Вы хотели бы предоставить keepReading в установщике, чтобы ваш основной класс / другие части приложения могли безопасно завершить поток без каких-либо других головных болей, просто вызвав stopReading() или что-то подобное.

Ответ 3

Проверьте JLogTailer, который выполняет эту логику.

Основным моментом в коде является:

public void run() {
try {
while (_running) {
Thread.sleep(_updateInterval);
long len = _file.length();
if (len < _filePointer) {
// Log must have been jibbled or deleted.
this.appendMessage("Log file was reset. Restarting logging from start of file.");
_filePointer = len;
}
else if (len > _filePointer) {
// File must have had something added to it!
RandomAccessFile raf = new RandomAccessFile(_file, "r");
raf.seek(_filePointer);
String line = null;
while ((line = raf.readLine()) != null) {
this.appendLine(line);
}
_filePointer = raf.getFilePointer();
raf.close();
}
}
}
catch (Exception e) {
this.appendMessage("Fatal error reading log file, log tailing has stopped.");
}
// dispose();
}
Ответ 4

Некоторое время назад я создал короткую реализацию "tail -f" в Scala: tailf. Он также заботится о ротации файлов, и вы можете определить свою собственную логику, что делать, когда он достигнет EOF или обнаружит, что файл был переименован.

Вы можете взглянуть и перенести его на Java, поскольку на самом деле там нет ничего сложного. Несколько замечаний: основным файлом является Tail.scala, и в основном он определяет, FollowingInputStream который обрабатывает EOF / rename и follow метод, который оборачивается FollowingInputStream в неограниченное перечисление в SequenceInputStream. Итак, как только FollowingInputStream завершается, SequenceInputStream запрашивается следующий элемент из Enumeration и создается еще один FollowingInputStream.

java file