In Java, was ist das beste / sicherste Muster zur Überwachung eine Datei zu angehängt wird?

StackOverflow https://stackoverflow.com/questions/1073274

  •  21-08-2019
  •  | 
  •  

Frage

jemand anderes Verfahren ist die Schaffung einer CSV-Datei, indem Sie eine Zeile zu einem Zeitpunkt, um es anhängt, als Ereignisse auftreten. Ich habe keine Kontrolle über das Dateiformat oder dem anderen Prozess, aber ich weiß, es wird nur anhängen.

In einem Java-Programm, würde Ich mag diese Datei überwachen, und wenn eine Zeile angefügt gelesen, um die neue Linie und reagiert entsprechend den Inhalt. Ignorieren Sie das CSV-Parsing Problem für jetzt. Was ist der beste Weg, um die Datei für Änderungen und liest eine Zeile zu einem Zeitpunkt zu überwachen?

Im Idealfall wird dies die Standardbibliothek Klassen verwenden. Die Datei kann auf einem Netzlaufwerk sein gut, so würde ich etwas robuster zum Scheitern mag. Ich möchte lieber nicht Polling verwenden, wenn möglich -. Ich eine Art lieber Blockierungslösung anstelle

Bearbeiten - vorausgesetzt, dass eine blockierende Lösung nicht möglich mit Standardklassen (Danke für die Antwort) ist, was ist die robusteste Polling Lösung? Ich möchte lieber nicht wieder lesen Sie die gesamte Datei jedes Mal, da es ziemlich groß werden könnte.

War es hilfreich?

Lösung

Da Java 7 gibt es die newWatchService () Methode auf der Filesystem-Klasse .

Es gibt jedoch einige Einschränkungen:

  • Es ist nur Java 7
  • Es ist eine optionale Methode
  • es nur Uhren Verzeichnisse, so müssen Sie die Datei tun Umgang mit sich selbst, und sorgen sich um die Datei zu bewegen etc

Vor Java 7 ist es nicht möglich, mit Standard-APIs.

Ich habe versucht, das folgende (Polling auf einem 1 sec-Intervall) und es funktioniert (nur druckt in Bearbeitung):

  private static void monitorFile(File file) throws IOException {
    final int POLL_INTERVAL = 1000;
    FileReader reader = new FileReader(file);
    BufferedReader buffered = new BufferedReader(reader);
    try {
      while(true) {
        String line = buffered.readLine();
        if(line == null) {
          // end of file, start polling
          Thread.sleep(POLL_INTERVAL);
        } else {
          System.out.println(line);
        }
      }
    } catch(InterruptedException ex) {
     ex.printStackTrace();
    }
  }

Wie niemand sonst eine Lösung vorgeschlagen hat, die eine aktuelle Produktion verwendet Java ich dachte ich, es würde hinzufügen. Wenn es Fehler sind fügen Sie bitte in den Kommentaren.

Andere Tipps

Sie können registrieren, indem Sie das Dateisystem informiert werden, wenn eine Änderung an der Datei geschieht WatchService Klasse. Dies erfordert Java7, hier den Link für die Dokumentation http://docs.oracle .com / JavaSE / tutorial / essential / io / notification.html

hier das Snippet Code zu tun:

public FileWatcher(Path dir) {
   this.watcher = FileSystems.getDefault().newWatchService();
   WatchKey key = dir.register(watcher, ENTRY_MODIFY);
}

void processEvents() {
    for (;;) {
        // wait for key to be signalled
        WatchKey key;
        try {
            key = watcher.take();
        } catch (InterruptedException x) {
            return;
        }

        for (WatchEvent<?> event : key.pollEvents()) {
            WatchEvent.Kind<?> kind = event.kind();

            if (kind == OVERFLOW) {
                continue;
            }
            // Context for directory entry event is the file name of entry
            WatchEvent<Path> ev = cast(event);
            Path name = ev.context();
            Path child = dir.resolve(name);
            // print out event
            System.out.format("%s: %s file \n", event.kind().name(), child);
        }
        // reset key and remove from set if directory no longer accessible
        boolean valid = key.reset();
    }
}

Mit Java 7 WatchService , Teil NIO.2

  

Die WatchService API ist für Anwendungen, die über Dateiänderungsereignisse informiert werden müssen.

Dies ist mit Standard-Bibliotheksklassen nicht möglich. Sehen Sie diese Frage .

Für eine effiziente Abfrage wird es besser sein Random Access . Es wird Ihnen helfen, wenn Sie die Position des letzten Ende der Datei erinnern und starten von dort zu lesen.

Just am letzten Eintrag Nick Fortescue zu erweitern, unten sind zwei Klassen, die gleichzeitig ausgeführt werden können (zB in zwei verschiedenen Windows-Shell), die zeigt, dass eine bestimmte Datei gleichzeitig von einem Prozess geschrieben werden kann und durch einen anderen zu lesen.

Hier werden die beiden Prozesse diese Java-Klassen werden die Ausführung, aber ich nehme an, dass der Schreibvorgang von einer anderen Anwendung sein könnte. (Unter der Annahme, dass es nicht eine exklusive Sperre für die hält Datei gibt es solche Dateisystemsperren für bestimmte Betriebssysteme?)

Ich habe erfolgreich getestet, diese beiden Klassen sowohl auf Windoof und Linux. Ich würde sehr gerne wissen, ob es einen Zustand (z Betriebssystem), auf dem sie scheitern.

Klasse 1:

import java.io.File;
import java.io.FileWriter;
import java.io.PrintWriter;

public class FileAppender {

    public static void main(String[] args) throws Exception {
        if ((args != null) && (args.length != 0)) throw
            new IllegalArgumentException("args is not null and is not empty");

        File file = new File("./file.txt");
        int numLines = 1000;
        writeLines(file, numLines);
    }

    private static void writeLines(File file, int numLines) throws Exception {
        PrintWriter pw = null;
        try {
            pw = new PrintWriter( new FileWriter(file), true );
            for (int i = 0; i < numLines; i++) {
                System.out.println("writing line number " + i);
                pw.println("line number " + i);
                Thread.sleep(100);
            }
        }
        finally {
            if (pw != null) pw.close();
        }
    }

}

Klasse # 2:

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;

public class FileMonitor {

    public static void main(String[] args) throws Exception {
        if ((args != null) && (args.length != 0)) throw
            new IllegalArgumentException("args is not null and is not empty");

        File file = new File("./file.txt");
        readLines(file);
    }

    private static void readLines(File file) throws Exception {
        BufferedReader br = null;
        try {
            br = new BufferedReader( new FileReader(file) );
            while (true) {
                String line = br.readLine();
                if (line == null) { // end of file, start polling
                    System.out.println("no file data available; sleeping..");
                    Thread.sleep(2 * 1000);
                }
                else {
                    System.out.println(line);
                }
            }
        }
        finally {
            if (br != null) br.close();
        }
    }

}

Leider TailInputStream-Klasse, die verwendet werden kann, um das Ende einer Datei zu überwachen, ist nicht einer von Standard-Java-Plattformklassen, aber es gibt nur wenige Implementierungen im Web. Sie können eine Implementierung von TailInputStream Klasse zusammen mit einem Anwendungsbeispiel auf http://www.greentelligent.com/java finden / tailinputstream .

Poll, entweder auf einem einheitlichen Zyklus oder an einem zufälligen Zyklus; 200-2000ms sollte eine guter Zufall Pollintervall Spanne sein.

Überprüfen Sie zwei Dinge ...

Wenn Sie Datei Wachstum beobachten haben, dann überprüfen Sie die EOF / Byte-Zählung, und sicher sein, dass und die Dateiablage oder Filewrite mal mit dem Mädel Umfrage zu vergleichen. Wenn (>), dann wird die Datei geschrieben.

Dann kombinieren, dass für exklusive Sperre mit der Überprüfung / Lesezugriff. Wenn die Datei schreib gesperrt werden kann und es ist gewachsen, dann was auch immer schreibt, um es fertig ist.

Überprüfen auf entweder Eigenschaft allein nicht unbedingt erhalten Sie einen garantierten Zustand ++ geschrieben und wirklich getan und verwendet werden können.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top