Реализация Java ввода-вывода в Unix/Линукс "хвост -Ф"
мне интересно, какие методы и / или библиотеки использовать для реализации функциональности команды 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
. Он должен иметь возможность читать части файла, которые существуют до открытия файла, а также строки, которые добавляются.
9 ответов:
возможность продолжать читать файл и ждать, пока файл не будет иметь еще несколько обновлений для вас не должно быть так сложно выполнить в коде самостоятельно. Вот какой-то псевдо-код:
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()
или что-то подобное.
взгляните на реализацию Apache Commons Tailer класса. Похоже, что он также обрабатывает вращение журнала.
Регистрация 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(); }
Я построил короткую реализацию "tail-f" в Scala некоторое время назад: tailf. Он также заботится о ротации файлов, и вы можете определить свою собственную логику, что делать, когда он достигает EOF или находит файл был переименован.
вы можете посмотреть и перевести его на Java, так как на самом деле там нет ничего сложного там. Несколько заметок: основной файл хвост.скала и в основном он определяет
FollowingInputStream
который заботится о EOF / переименовать иfollow
метод, который обертываетFollowingInputStream
в неограниченное перечисление вSequenceInputStream
. Итак, как толькоFollowingInputStream
заканчиваетсяSequenceInputStream
запрашивает следующий элемент изEnumeration
и еще один получает.
Я недавно наткнулся на rxjava-file, Это -RxJava. В отличие от других решений, это использует Nio Java.
import rx.Observable; import rx.functions.Action1; import com.github.davidmoten.rx.FileObservable; // ... class definition omitted public void tailLogFile() throws InterruptedException { Observable<String> tailer = FileObservable.tailer() .file("application.log") // absolute path .tailText(); tailer.subscribe( new Action1<String>() { @Override public void call(String line) { System.out.println("you got line: " + line); } }, new Action1<Throwable>() { @Override public void call(Throwable e) { System.out.println("you got error: " + e); e.printStackTrace(); } } ); // this solution operates threaded, so something // is required that prevents premature termination Thread.sleep(120000); }
вот краткий рассказ, который вы могли бы использовать в качестве указателя:
я закодировал TailingInputStream на работе по той же причине. Он в основном использует файл и обновляет его содержимое по требованию и проверяет внутренний буфер, если он значительно изменился (4KB Memory stamp IIRC), а затем сделал то, что делает хвост-f. Немного хаки, да, но он отлично работает и не связывается с потоками или чем - то подобным-он совместим с 1.4.2 at наименьший.
тем не менее, это было намного проще сделать, чем ReverseInputStream, который шел от конца файла до начала и не умирал, если файл обновлялся на лету...
Если ваш код только когда-либо придется работать на системах Unix, вы можете быть в состоянии уйти с просто обстрел и вызов
tail -f
напрямую.в качестве более сложной альтернативы вы можете взглянуть на реализацию хвоста GNU и порта, который переходит на Java. (Я не уверен, что это уже не сделает ваш код производной работой.)
просто столкнулся с той же проблемой - нашел "простой" реализации здесь: Java Tail.
*большой материал * - готова к работе ;)
Я надеюсь, что код-цитата не упадет некоторые лицензии.
import java.io.BufferedReader; import java.io.FileReader; import java.io.IOException; /** * Java implementation of the Unix tail command * * @param args[0] File name * @param args[1] Update time (seconds). Optional. Default value is 1 second * * @author Luigi Viggiano (original author) http://it.newinstance.it/2005/11/19/listening-changes-on-a-text-file-unix-tail-implementation-with-java/ * @author Alessandro Melandri (modified by) * */ public class Tail { static long sleepTime = 1000; public static void main(String[] args) throws IOException { if (args.length > 0){ if (args.length > 1) sleepTime = Long.parseLong(args[1]) * 1000; BufferedReader input = new BufferedReader(new FileReader(args[0])); String currentLine = null; while (true) { if ((currentLine = input.readLine()) != null) { System.out.println(currentLine); continue; } try { Thread.sleep(sleepTime); } catch (InterruptedException e) { Thread.currentThread().interrupt(); break; } } input.close(); } else { System.out.println("Missing parameter!\nUsage: java JavaTail fileName [updateTime (Seconds. default to 1 second)]"); } } }
Я нашел эту хорошую реализацию хвоста.
автор : amelandri
соус от:https://gist.github.com/amelandri/1376896
import java.io.BufferedReader; import java.io.FileReader; import java.io.IOException; /** * Java implementation of the Unix tail command * * @param args[0] File name * @param args[1] Update time (seconds). Optional. Default value is 1 second * * @author Luigi Viggiano (original author) http://it.newinstance.it/2005/11/19/listening-changes-on-a-text-file-unix-tail-implementation-with-java/ * @author Alessandro Melandri (modified by) * */ public class Tail { static long sleepTime = 1000; public static void main(String[] args) throws IOException { if (args.length > 0){ if (args.length > 1) sleepTime = Long.parseLong(args[1]) * 1000; BufferedReader input = new BufferedReader(new FileReader(args[0])); String currentLine = null; while (true) { if ((currentLine = input.readLine()) != null) { System.out.println(currentLine); continue; } try { Thread.sleep(sleepTime); } catch (InterruptedException e) { Thread.currentThread().interrupt(); break; } } input.close(); } else { System.out.println("Missing parameter!\nUsage: java JavaTail fileName [updateTime (Seconds. default to 1 second)]"); } } }