Мне интересно, какие методы и / или библиотеку использовать для реализации функциональности команды Linux "tail -f". По сути, я ищу дополнение / замену для java.io.FileReader. Клиентский код может выглядеть примерно так:
TailFileReaderlft=newTailFileReader("application.log"); BufferedReaderbr=newBufferedReader(lft); String line; try { while (true) { line= br.readLine(); // do something interesting with line } } catch (IOException e) { // barf }
Недостающая часть является разумной реализацией TailFileReader. Он должен иметь возможность считывать части файла, которые существовали до открытия файла, а также добавленные строки.
Переведено автоматически
Ответ 1
Взгляните на реализацию класса Tailer на Apache Commons. Похоже, он также обрабатывает ротацию журналов.
Ответ 2
Возможность продолжить чтение файла и подождать, пока в файле появятся дополнительные обновления для вас, не должна быть такой сложной для выполнения в коде самостоятельно. Вот несколько псевдокодов:
BufferedReaderbr=newBufferedReader(...); 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, который выполняет эту логику.
Основным моментом в коде является:
publicvoidrun() { try { while (_running) { Thread.sleep(_updateInterval); longlen= _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; } elseif (len > _filePointer) { // File must have had something added to it! RandomAccessFileraf=newRandomAccessFile(_file, "r"); raf.seek(_filePointer); Stringline=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.