2010-02-05 16 views
13

Estoy tratando de ver cómo leer continuamente un archivo y una vez que hay una nueva línea agregada, muestra la línea. Estoy haciendo esto usando un hilo de suspensión, pero parece que soplará todo el archivo y saldrá del programa.¿Cómo se lee continuamente un archivo en Java?

¿Alguna sugerencia de lo que estoy haciendo mal?

Aquí está mi código:

import java.io.*; 
import java.lang.*; 
import java.util.*; 

class jtail { 
    public static void main (String args[]) 
      throws InterruptedException, IOException{ 

     BufferedReader br = new BufferedReader(
       new FileReader("\\\\server01\\data\\CommissionPlanLog.txt")); 

     String line = null; 
     while (br.nextLine) { 
      line = br.readLine(); 
      if (line == null) { 
       //wait until there is more of the file for us to read 
       Thread.sleep(1000); 
      } 
      else { 
       System.out.println(line); 
      } 
     } 
    } //end main 
} //end class jtail 

gracias de antemano

ACTUALIZACIÓN: Desde entonces, he cambiado la línea "mientras que (br.nextLine) {" a sólo "while (true) {"

+0

Este código no se compilará. ¿Qué es 'in'? –

+0

Solo un comentario, pero debe considerar el uso de objetos de escáner en lugar de BufferedReader, tienden a ser más amigables, sin embargo, eso no responderá a esta pregunta. – Pace

+0

Todavía no está bien en: 'while (br.nextLine)', 'nextLine no es un campo válido de' BufferedReader'. –

Respuesta

15

Esto en algo viejo, pero he usado el mecanismo y funciona bastante bien.

edición: enlace ya no funciona, pero lo encontré en el archivo de Internet https://web.archive.org/web/20160510001134/http://www.informit.com/guides/content.aspx?g=java&seqNum=226

El truco es usar un java.io.RandomAccessFile, y comprobar periódicamente si la longitud del archivo es mayor que su posición actual del fichero. Si es así, entonces usted lee los datos. Cuando alcanzas la longitud, esperas. lavar, enjuagar, repetir.

He copiado el código, sólo en caso de que el nuevo enlace deja de funcionar

package com.javasrc.tuning.agent.logfile; 

import java.io.*; 
import java.util.*; 

/** 
* A log file tailer is designed to monitor a log file and send notifications 
* when new lines are added to the log file. This class has a notification 
* strategy similar to a SAX parser: implement the LogFileTailerListener interface, 
* create a LogFileTailer to tail your log file, add yourself as a listener, and 
* start the LogFileTailer. It is your job to interpret the results, build meaningful 
* sets of data, etc. This tailer simply fires notifications containing new log file lines, 
* one at a time. 
*/ 
public class LogFileTailer extends Thread 
{ 
    /** 
    * How frequently to check for file changes; defaults to 5 seconds 
    */ 
    private long sampleInterval = 5000; 

    /** 
    * The log file to tail 
    */ 
    private File logfile; 

    /** 
    * Defines whether the log file tailer should include the entire contents 
    * of the exising log file or tail from the end of the file when the tailer starts 
    */ 
    private boolean startAtBeginning = false; 

    /** 
    * Is the tailer currently tailing? 
    */ 
    private boolean tailing = false; 

    /** 
    * Set of listeners 
    */ 
    private Set listeners = new HashSet(); 

    /** 
    * Creates a new log file tailer that tails an existing file and checks the file for 
    * updates every 5000ms 
    */ 
    public LogFileTailer(File file) 
    { 
    this.logfile = file; 
    } 

    /** 
    * Creates a new log file tailer 
    * 
    * @param file   The file to tail 
    * @param sampleInterval How often to check for updates to the log file (default = 5000ms) 
    * @param startAtBeginning Should the tailer simply tail or should it process the entire 
    *    file and continue tailing (true) or simply start tailing from the 
    *    end of the file 
    */ 
    public LogFileTailer(File file, long sampleInterval, boolean startAtBeginning) 
    { 
    this.logfile = file; 
    this.sampleInterval = sampleInterval; 
    } 

    public void addLogFileTailerListener(LogFileTailerListener l) 
    { 
    this.listeners.add(l); 
    } 

    public void removeLogFileTailerListener(LogFileTailerListener l) 
    { 
    this.listeners.remove(l); 
    } 

    protected void fireNewLogFileLine(String line) 
    { 
    for(Iterator i=this.listeners.iterator(); i.hasNext();) 
    { 
     LogFileTailerListener l = (LogFileTailerListener)i.next(); 
     l.newLogFileLine(line); 
    } 
    } 

    public void stopTailing() 
    { 
    this.tailing = false; 
    } 

    public void run() 
    { 
    // The file pointer keeps track of where we are in the file 
    long filePointer = 0; 

    // Determine start point 
    if(this.startAtBeginning) 
    { 
     filePointer = 0; 
    } 
    else 
    { 
     filePointer = this.logfile.length(); 
    } 

    try 
    { 
     // Start tailing 
     this.tailing = true; 
     RandomAccessFile file = new RandomAccessFile(logfile, "r"); 
     while(this.tailing) 
     { 
     try 
     { 
      // Compare the length of the file to the file pointer 
      long fileLength = this.logfile.length(); 
      if(fileLength < filePointer) 
      { 
      // Log file must have been rotated or deleted; 
      // reopen the file and reset the file pointer 
      file = new RandomAccessFile(logfile, "r"); 
      filePointer = 0; 
      } 

      if(fileLength > filePointer) 
      { 
      // There is data to read 
      file.seek(filePointer); 
      String line = file.readLine(); 
      while(line != null) 
      { 
       this.fireNewLogFileLine(line); 
       line = file.readLine(); 
      } 
      filePointer = file.getFilePointer(); 
      } 

      // Sleep for the specified interval 
      sleep(this.sampleInterval); 
     } 
     catch(Exception e) 
     { 
     } 
     } 

     // Close the file that we are tailing 
     file.close(); 
    } 
    catch(Exception e) 
    { 
     e.printStackTrace(); 
    } 
    } 
} 
+0

El enlace ya no apunta a una guía de ejemplo. – makadus

+1

enlace fijo y código copiado en la respuesta – karoberts

+0

¡Impresionante, gracias! – makadus

2

La forma en que se escribe el código ahora, no pasará por el ciclo while cuando su 'línea == nulo' porque está comprobando que tiene una línea siguiente antes de entrar en el ciclo.

En su lugar, intente hacer un bucle while(true){ }. De esta forma, siempre estará recorriendo todo el tiempo, atrapando sus casos de pausa, hasta que llegue a una condición que haría que el programa termine.

5

Si está planeando implementar esto en una aplicación de tamaño razonable, donde varios objetos podrían estar interesados ​​en el procesamiento de las nuevas líneas que vienen a el archivo, es posible que desee considerar el patrón Observer.

El objeto que se lee del archivo notificará a cada objeto suscrito tan pronto como se haya procesado una línea. Esto le permitirá mantener la lógica bien separada en la clase donde se necesita.

Cuestiones relacionadas