DISABILITARE ADBLOCK

ADBlock sta bloccando alcuni contenuti del sito

ADBlock errore
risultati trovati: 

DOMANDA

Ho un'applicazione che scrive informazioni su file. Queste informazioni vengono utilizzate dopo l'esecuzione per determinare il passaggio / errore / correttezza dell'applicazione. Mi piacerebbe poter leggere il file mentre viene scritto in modo da poter eseguire questi controlli di superamento / fallimento / correttezza in tempo reale.

Presumo sia possibile farlo, ma quali sono i gotcha coinvolti nell'uso di Java? Se la lettura raggiunge la scrittura, aspetterà solo più scritture fino alla chiusura del file o la lettura genererà un'eccezione a questo punto? In quest'ultimo caso, cosa devo fare?

La mia intuizione mi sta spingendo verso BufferedStreams. È questa la strada da percorrere?

SOLUZIONE

Non è stato possibile far funzionare l'esempio usando FileChannel.read (ByteBuffer) perché non è una lettura bloccante. Tuttavia, il codice riportato di seguito funziona:

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

Ovviamente la stessa cosa funzionerebbe come un timer anziché come un thread, ma lo lascio al programmatore. Sto ancora cercando un modo migliore, ma per ora funziona per me.

Oh, e lo avvertirò con: sto usando 1.4.2. Sì, lo so che sono ancora nell'età della pietra.

Se ti va lasciaci una tua opinione

L'articolo ti è stato utile ed è tradotto correttamente?

ALTRI SUGGERIMENTI

Se vuoi leggere un file mentre è in fase di scrittura e leggere solo il nuovo contenuto, seguire quanto segue ti aiuterà a ottenere lo stesso.

Per eseguire questo programma, lo avvierai dal prompt dei comandi / finestra del terminale e passerai il nome del file da leggere. Leggerà il file a meno che non si uccida il programma.

java FileReader c: \ myfile.txt

Mentre digiti una riga di testo salvala dal blocco note e vedrai il testo stampato nella console.

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

Potresti anche dare un'occhiata al canale Java per bloccare una parte di un file.

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

Questa funzione del FileChannel potrebbe essere un inizio

lock(long position, long size, boolean shared) 

Un'invocazione di questo metodo si bloccherà fino a quando l'area non può essere bloccata

Sono totalmente d'accordo con la risposta di Joshua , Tailer è adatto per il lavoro in questa situazione. Ecco un esempio:

Scrive una riga ogni 150 ms in un file, mentre legge questo stesso file ogni 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);
        }
    }
}

La risposta sembra essere " no " ... e "sì". Non sembra esserci un vero modo per sapere se un file è aperto per la scrittura da un'altra applicazione. Quindi, la lettura da un tale file procederà solo fino all'esaurimento del contenuto. Ho seguito il consiglio di Mike e ho scritto un codice di prova:

Writer.java scrive una stringa su file e quindi attende che l'utente prema invio prima di scrivere un'altra riga su file. L'idea è che potrebbe essere avviato, quindi un lettore può essere avviato per vedere come affronta il "parziale" file. Il lettore che ho scritto è 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);
    }
}

Nessuna garanzia che questo codice sia la migliore pratica.

Questo lascia l'opzione suggerita da Mike di controllare periodicamente se ci sono nuovi dati da leggere dal file. Ciò richiede quindi l'intervento dell'utente per chiudere il lettore di file quando si determina che la lettura è stata completata. Oppure, il lettore deve essere informato del contenuto del file ed essere in grado di determinare e terminare le condizioni di scrittura. Se il contenuto fosse XML, la fine del documento potrebbe essere utilizzata per segnalare questo.

Non Java di per sé, ma potresti riscontrare problemi in cui hai scritto qualcosa in un file, ma non è stato ancora effettivamente scritto - potrebbe essere in una cache da qualche parte e la lettura dallo stesso file potrebbe non in realtà ti danno le nuove informazioni.

Versione breve: utilizzare flush () o qualunque sia la chiamata di sistema pertinente per assicurarsi che i dati siano effettivamente scritti nel file.

Nota Non sto parlando della cache del disco a livello di sistema operativo - se i tuoi dati entrano qui, dovrebbero apparire in un read () dopo questo punto. È possibile che la lingua stessa scriva nella cache, in attesa che un buffer si riempia o che il file venga scaricato / chiuso.

Esiste una coda grafica Java open source che lo fa.

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

Non l'ho mai provato, ma dovresti scrivere un test case per vedere se la lettura da uno stream dopo che hai raggiunto la fine funzionerà, indipendentemente dal fatto che ci siano più dati scritti nel file.

C'è un motivo per cui non è possibile utilizzare un flusso di input / output collegato? I dati vengono scritti e letti dalla stessa applicazione (in tal caso, si dispone dei dati, perché è necessario leggere dal file)?

Altrimenti, potresti leggere fino alla fine del file, quindi monitorare le modifiche e cercare dove hai interrotto e continuare ... ma fai attenzione alle condizioni della gara.

Non puoi leggere un file che viene aperto da un altro processo usando FileInputStream, FileReader o RandomAccessFile.

Ma l'uso diretto di FileChannel funzionerà:

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