Ich frage mich, welche Techniken und / oder Bibliotheken verwendet werden sollen, um die Funktionalität des Linux-Befehls "tail -f" zu implementieren. Ich bin im Wesentlichen auf der Suche nach einem Tropfen Add-On / Ersatz für java.io.FileReader
. Der Client-Code könnte ungefähr so aussehen:
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
}
Das fehlende Stück ist eine vernünftige Umsetzung von TailFileReader
. Es sollte in der Lage sein, Teile der Datei zu lesen, die vor dem Öffnen der Datei vorhanden sind, sowie die hinzugefügten Zeilen.
Schauen Sie sich die Apache Commons-Implementierung der Tailer- Klasse an. Es scheint auch die Protokollrotation zu handhaben.
quelle
Überprüfen Sie JLogTailer , der diese Logik ausführt .
Der Hauptpunkt im Code ist:
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(); }
quelle
Ich habe vor einiger Zeit eine kurze Implementierung von "tail -f" in Scala erstellt: tailf . Es kümmert sich auch um die Dateirotation und Sie können Ihre eigene Logik definieren, was zu tun ist, wenn EOF erreicht wird oder festgestellt wird, dass die Datei umbenannt wurde.
Sie können einen Blick darauf werfen und es nach Java portieren, da dort eigentlich nichts Komplexes ist. Einige Anmerkungen: Die Hauptdatei ist Tail.scala und definiert im Grunde genommen,
FollowingInputStream
was sich um EOF / Umbenennung undfollow
Methode kümmert , wasFollowingInputStream
in eine unbegrenzte Aufzählung in umschließtSequenceInputStream
. Sobald diesFollowingInputStream
endet, werdenSequenceInputStream
Anforderungen für das nächste Element von einemEnumeration
und einem anderenFollowingInputStream
erstellt.quelle
Ich bin kürzlich über die rxjava-Datei gestolpert . Es ist eine Erweiterung von RxJava . Im Gegensatz zu den anderen Lösungen wird hier das NIO von Java verwendet.
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); }
quelle
Wenn Ihr Code immer nur auf Unix-Systemen ausgeführt werden muss, können Sie möglicherweise einfach loslegen und
tail -f
direkt anrufen .Als komplexere Alternative können Sie sich die Implementierung von GNU Tail ansehen und diese auf Java übertragen. (Ich bin mir nicht sicher, ob dies Ihren Code nicht bereits zu einer abgeleiteten Arbeit machen würde.)
quelle
tail -f
Wird die Java-App hängen bleiben, wenn sie niemals beendet wird?Just war mit dem gleichen Problem konfrontiert - fand die "einfachste" Implementierung hier: Java Tail .
* Tolles Zeug * - fertig zur Produktion;)
Ich hoffe, dass das Code-Zitat keine Lizenz fallen lässt.
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)]"); } } }
quelle
Ich habe diese schöne Schwanzimplementierung gefunden.
Verfasser: amelandri
Quelle von: 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)]"); } } }
quelle
Hier ist eine Kurzgeschichte, die Sie als Zeiger verwenden können:
Ich habe TailingInputStream bei der Arbeit aus dem gleichen Grund codiert. Grundsätzlich verwendet es File und aktualisiert seinen Inhalt bei Bedarf und vergleicht ihn mit dem internen Puffer, wenn er sich erheblich geändert hat (4 KB Speicherstempel IIRC), und hat dann das getan, was das tail -f tut. Ein bisschen hackig, ja, aber es funktioniert perfekt und spielt nicht mit Threads oder Ähnlichem - es ist mindestens bis 1.4.2 kompatibel.
Das heißt, es war viel einfacher als ReverseInputStream, das vom Ende der Datei bis zum Start ging und nicht starb, wenn die Datei im laufenden Betrieb aktualisiert wurde ...
quelle