Ich habe eine benutzerdefinierte Protokollierungsklasse geschrieben, die sich einem PrintWriter wie System.out oder System.err sehr ähnlich verhält. Der Hauptunterschied besteht darin, dass beim Aufruf von myLogger.printf("Hello World!\n");
die Daten nicht direkt in die Protokolldatei, sondern in eine interne Warteschlange geschrieben werden und diese Warteschlange nur über die Methode flush();
in die Ausgabedatei geleert wird. So Verwendung des Codes sieht wie folgt aus:Wie kann sichergestellt werden, dass die Methode aufgerufen wird, bevor das Objekt zerstört wird?
myLogger.println("Line 1.");
myLogger.println("Line 3.");
myLogger.println("Actually that was Line 2. THIS is Line 3!");
myLogger.flush();
, die einen Ausgang geben sollte, die (Art) wie folgt aussieht:
2016-03-30 15:44:45::389> Line 1.
2016-03-30 15:44:45::390> Line 3.
2016-03-30 15:44:45::395> Actually that was Line 2. THIS is Line 3!
jedoch das Problem, das ich habe, ist, wenn Benutzer Fehler machen. Sie vergessen nämlich, flush()
aufzurufen, und die Daten, die sie in den Logger geschrieben haben, werden nie in die Datei geschrieben, und das Programm wird geschlossen, ohne die Daten zu löschen.
Ich kann nicht nach jedem einzelnen Aufruf flush, weil es den Zweck des Schreibens dieser Klasse an erster Stelle besiegen würde. Und das automatische Spülen des Systems zu verwalten wäre in ähnlicher Weise selbstzerstörerisch.
Meine Idee war, einen Anruf zu flush()
innerhalb der finalize()
Methode des Objekts zu setzen, aber wie ich von several other articles auf dieser Seite gelesen habe, gibt es keine Garantie, dass finalize()
jemals aufgerufen werden.
Nur für Klarheit willen, ist es das, was die flush()
Methode wie folgt aussieht:
public void flush() {
open();
while(!unwrittenLogs.isEmpty()) {
String line = unwrittenLogs.poll();
log.print(line);
}
close();
}
private void open() {
if(log == null) {
try {
log = new PrintWriter(new FileOutputStream(logFile, true));
} catch (FileNotFoundException e) {
System.err.printf("Unable to open Log File.\n%s\n",e.getMessage());
e.printStackTrace(System.err);
}
}
}
private void close() {
if(log != null) {
log.close();
log = null;
}
}
Also, was ist meine beste Option, um sicherzustellen, dass der Logger gespült wird, bevor das Programm beendet wird?
Es gibt zwei Dinge, die Sie tun können: Flush nach jedem X schreibt, wo X konfigurierbar ist. Sie können auch [shutdown hook] (https://docs.oracle.com/javase/8/docs/api/java/lang/Runtime.html#addShutdownHook-java.lang.Thread-) registrieren, die 'flush () 'ein letztes Mal. Der Shutdown-Hook wird auch nicht immer aufgerufen, da die VM möglicherweise einfach abstürzt. – biziclop
Es gibt auch ein subtiles Datenrennen in Ihrem Code: wenn 'flush()' aufgerufen wird, kann ein anderer Thread noch Nachrichten in Ihrem Logger veröffentlichen. Wenn also 'close()' aufgerufen wird, können 'ungeschriebeneLogs' noch Einträge haben wird still fallen gelassen. – biziclop