ADBLOCK DEAKTIVIEREN

ADBlock blockiert einige Inhalte auf der Website

ADBlock errore

Wie kann ich Java verwenden aus einer Datei zu lesen, die aktiv geschrieben wird?

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

Frage

Ich habe eine Anwendung, die Informationen schreibt Datei. Diese Informationen werden nach der Ausführung verwendet, um Pass / Fehler / Richtigkeit der Anwendung zu bestimmen. Ich möchte in der Lage sein, die Datei zu lesen, wie es geschrieben wird, so dass ich diese Bestanden / Versagen tun können / Richtigkeit überprüft in Echtzeit.

Ich gehe davon aus es möglich ist, dies zu tun, aber was ist die beteiligten des Gotcha bei der Verwendung von Java? Wenn das Lesen zum Schreiben einholt, wird es nur für mehr warten schreibt, bis die Datei geschlossen wird, oder wird die Lese eine Ausnahme an dieser Stelle werfen? Wenn letzteres der Fall, was soll ich tun dann?

Meine Intuition zur Zeit drängt mich in Richtung BufferedStreams. Ist dies der Weg zu gehen?

Lösung

kann nicht das Beispiel erhält mit FileChannel.read(ByteBuffer) zu arbeiten, weil es nicht eine blockierende Lese ist. aber Haben Sie den Code unten an der Arbeit:

boolean running = true;
BufferedInputStream reader = new BufferedInputStream(new FileInputStream( "out.txt" ) );

public void run() {
    while( running ) {
        if( reader.available() > 0 ) {
            System.out.print( (char)reader.read() );
        }
        else {
            try {
                sleep( 500 );
            }
            catch( InterruptedException ex ) {
                running = false;
            }
        }
    }
}

Natürlich ist die gleiche Sache würde als Timer arbeiten, anstatt ein Threads, aber ich überlasse das den Programmierer auf. Ich bin noch auf der Suche nach einem besseren Weg, aber das funktioniert für mich jetzt.

Oh, und ich werde Caveat dies mit: Ich bin mit 1.4.2. Ja, ich weiß, dass ich immer noch in der Steinzeit bin.

ANDERE TIPPS

Wenn Sie eine Datei zu lesen, während es geschrieben wird und lesen nur die neuen Inhalte dann folgenden werden Ihnen helfen, das gleiche zu erreichen.

Um dieses Programm ausführen Sie es von Eingabeaufforderung / Terminal-Fenster starten wird und den Dateinamen übergeben zu lesen. Es wird die Datei lesen, wenn Sie das Programm zu töten.

java Filereader c: \ myfile.txt

Wie Sie eine Textzeile eingeben, speichern Sie es aus Notizblock und Sie werden den Text gedruckt in der Konsole angezeigt.

public class FileReader {

    public static void main(String args[]) throws Exception {
        if(args.length>0){
            File file = new File(args[0]);
            System.out.println(file.getAbsolutePath());
            if(file.exists() && file.canRead()){
                long fileLength = file.length();
                readFile(file,0L);
                while(true){

                    if(fileLength<file.length()){
                        readFile(file,fileLength);
                        fileLength=file.length();
                    }
                }
            }
        }else{
            System.out.println("no file to read");
        }
    }

    public static void readFile(File file,Long fileLength) throws IOException {
        String line = null;

        BufferedReader in = new BufferedReader(new java.io.FileReader(file));
        in.skip(fileLength);
        while((line = in.readLine()) != null)
        {
            System.out.println(line);
        }
        in.close();
    }
}

Sie können auch einen Blick auf Java-Kanal nehmen Sie einen Teil einer Datei zur Verriegelung.

http: //java.sun. com / JavaSE / 6 / docs / api / java / nio / channels / FileChannel.html

Diese Funktion des FileChannel könnte ein Anfang sein

lock(long position, long size, boolean shared) 

Ein Aufruf dieser Methode wird blockiert, bis der Bereich kann gesperrt werden,

Ich bin vollkommen einverstanden mit Joshua Antwort Tailer für den Job in dieser Situation geeignet ist. Hier ein Beispiel:

Es schreibt eine Zeile alle 150 ms in einer Datei, während diese gleiche Datei zu lesen all 2500 ms

public class TailerTest
{
    public static void main(String[] args)
    {
        File f = new File("/tmp/test.txt");
        MyListener listener = new MyListener();
        Tailer.create(f, listener, 2500);

        try
        {
            FileOutputStream fos = new FileOutputStream(f);
            int i = 0;
            while (i < 200)
            {
                fos.write(("test" + ++i + "\n").getBytes());
                Thread.sleep(150);
            }
            fos.close();
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }
    }

    private static class MyListener extends TailerListenerAdapter
    {
        @Override
        public void handle(String line)
        {
            System.out.println(line);
        }
    }
}

Die Antwort scheint „Nein“ ... und „Ja“ zu sein. Es scheint keine wirkliche Möglichkeit zu sein, zu wissen, ob eine Datei für das Schreiben von einer anderen Anwendung geöffnet ist. Also, aus einer solchen Datei zu lesen wird nur Fortschritte, bis Inhalt erschöpft ist. Ich nahm Mike Rat und schrieb einigen Test-Code:

Writer.java schreibt eine Zeichenkette in Datei und wartet dann darauf, dass der Benutzer vor dem Schreiben eine weitere Zeile eingeben zu schlagen Datei. Die Idee ist, dass es in Betrieb genommen werden kann, dann kann ein Leser gestartet werden, um zu sehen, wie es mit der „teilweise“ Datei meistert. Der Leser schrieb ich in Reader.java.

Writer.java

public class Writer extends Object
{
    Writer () {

    }

    public static String[] strings = 
        {
            "Hello World", 
            "Goodbye World"
        };

    public static void main(String[] args) 
        throws java.io.IOException {

        java.io.PrintWriter pw =
            new java.io.PrintWriter(new java.io.FileOutputStream("out.txt"), true);

        for(String s : strings) {
            pw.println(s);
            System.in.read();
        }

        pw.close();
    }
}

Reader.java

public class Reader extends Object
{
    Reader () {

    }

    public static void main(String[] args) 
        throws Exception {

        java.io.FileInputStream in = new java.io.FileInputStream("out.txt");

        java.nio.channels.FileChannel fc = in.getChannel();
        java.nio.ByteBuffer bb = java.nio.ByteBuffer.allocate(10);

        while(fc.read(bb) >= 0) {
            bb.flip();
            while(bb.hasRemaining()) {
                System.out.println((char)bb.get());
            }
            bb.clear();
        }

        System.exit(0);
    }
}

keine Garantie, dass dieser Code beste Vorgehensweise ist.

Dies läßt die von Mike vorgeschlagen Möglichkeit, in regelmäßigen Abständen überprüft, ob neue Daten aus der Datei gelesen werden. Dies erfordert dann Benutzereingriff die Datei Leser zu schließen, wenn festgestellt wird, dass das Lesen abgeschlossen ist. Oder muss der Leser darauf aufmerksam gemacht werden, um den Inhalt der Datei und in der Lage zu bestimmen, und das Ende der Schreibbedingung. Wenn der Inhalt XML, könnte das Ende des Dokuments verwendet werden, um dies zu signalisieren.

Nicht Java per se, aber Sie können auf Probleme stoßen, wo man etwas in eine Datei geschrieben, aber es wurde nicht noch tatsächlich geschrieben - es irgendwo in einem Cache sein könnte, und aus der gleichen Datei lesen können nicht tatsächlich gibt Ihnen die neuen Informationen.

Kurzversion -. Verwendung flush () oder was auch immer der entsprechende Systemaufruf ist, um sicherzustellen, dass Ihre Daten tatsächlich in die Datei geschrieben wird

Hinweis: Ich spreche nicht über die OS-Ebene Disk-Cache - wenn Sie Ihre Daten in herkommt, ist es in einem read () nach diesem Zeitpunkt erscheinen soll. Es kann sein, dass die Sprache selbst Caches schreibt, zu warten, bis ein Puffer voll ist oder die Datei wird gespült / geschlossen.

Es gibt einen Open-Source-Java-Grafik-Schwanz, der dies tut.

https://stackoverflow.com/a/559146/1255493

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();
}

Ich habe nie versucht es, aber man sollte einen Testfall zu sehen, ob aus einem Stream schreiben zu lesen, nachdem Sie das Ende funktioniert getroffen haben, unabhängig davon, ob es mehr Daten in die Datei geschrieben.

Gibt es einen Grund, warum Sie nicht verrohrt Eingabe / Ausgabe-Stream verwenden können? Sind die Daten werden von der gleichen Anwendung geschrieben und gelesen werden (wenn ja, Sie die Daten haben, warum haben Sie aus der Datei lesen müssen)?

Ansonsten lesen vielleicht bis zum Ende der Datei, dann für Änderungen überwachen und versuchen, wo Sie links abbiegen und weiter ... obwohl für Rennbedingungen achten.

Sie können eine Datei nicht lesen, die von einem anderen Prozess geöffnet wird mit Fileinputstream, Filereader oder Random.

Aber mit Filechannel direkt funktioniert:

private static byte[] readSharedFile(File file) throws IOException {
    byte buffer[] = new byte[(int) file.length()];
    final FileChannel fc = FileChannel.open(file.toPath(), EnumSet.of(StandardOpenOption.READ));
    final ByteBuffer dst = ByteBuffer.wrap(buffer);
    fc.read(dst);
    fc.close();
    return buffer;
}

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow