70 votes

Application Java IO d’unix/linux « tail -f »

Je me demande quelles techniques et / ou bibliothèque utiliser pour implémenter les fonctionnalités de la commande linux "tail -f". Je cherche essentiellement une solution complémentaire / de remplacement pour java.io.FileReader. Le code client pourrait ressembler à ceci:

 TailFileReader lft = new TailFileReader("application.log");
BufferedReader br = new BufferedReader(lft);
String line;
try {
  while (true) {
    line= br.readLine();
    // do something interesting with line
  }
} catch (IOException e) {
  // barf
}
 

La pièce manquante est une implémentation raisonnable de TailFileReader. Il devrait être capable de lire des parties du fichier qui existaient avant son ouverture, ainsi que les lignes ajoutées.

59voto

Chetan Sastry Points 14742

Jetez un coup d'œil à l'implémentation Apache Commons de la classe Tailer . Il semble également gérer la rotation des journaux.

37voto

matt b Points 73770

La capacité de continuer à lire un fichier, et attendre jusqu'à ce que le fichier a plus de mises à jour pour vous ne devrait pas être difficile à accomplir dans le code vous-même. Voici quelques pseudo-code:

BufferedReader br = new BufferedReader(...);
String line;
while (keepReading) {
    line = reader.readLine();
    if (line == null) {
        //wait until there is more of the file for us to read
        Thread.sleep(1000);
    }
    else {
        //do something interesting with the line
    }
}

Je suppose que vous voulez mettre en œuvre ce type de fonctionnalité dans son propre Thread, de sorte que vous pouvez dormir et ne pas affecter d'autres domaines de votre application. Vous souhaitez exposer keepReading dans un setter de sorte que votre classe principale / autres parties de l'application peut en toute sécurité fermer le fil vers le bas, sans autres maux de tête, simplement en appelant stopReading() ou quelque chose de similaire.

12voto

aldrinleal Points 2188

Vérifiez JLogTailer , qui effectue cette logique.

Le point principal dans le code est:

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

9voto

Alexander Azarov Points 6630

J'ai construit un court de mise en place de "tail-f" à la Scala il y a quelques temps: tailf. Il prend soin de rotation de fichier et vous pouvez définir votre propre logique quoi faire quand il atteint expressions du FOLKLORE, ou se trouve le fichier a été renommé.

Vous pouvez prendre un coup d'oeil et port de Java, car effectivement il n'y a rien de complexe. Quelques remarques: le fichier principal est la Queue.scala et, essentiellement, il définit FollowingInputStream qui prend soin de EOF/renommer et follow méthode, qui s'enroule FollowingInputStream dans un abîme d'énumération en SequenceInputStream. Aussi, dès qu' FollowingInputStream se termine, SequenceInputStream demandes de l'élément suivant à partir d'un Enumeration et un autre FollowingInputStream est créé.

0voto

ViPup Points 21

Juste était confronté au même problème - trouvé la "plus simple" implémentation ici: Java Tail .

* Très bon matériel * - prêt pour la production;)

J'espère que la citation de code ne laissera pas tomber une licence.

     import java.io.BufferedReader;
    import java.io.FileReader;
    import java.io.IOException;

    /**
     * Java implementation of the Unix tail command
     * 
     * @param args[0] File name
     * @param args[1] Update time (seconds). Optional. Default value is 1 second
     * 
     * @author Luigi Viggiano (original author) http://it.newinstance.it/2005/11/19/listening-changes-on-a-text-file-unix-tail-implementation-with-java/
     * @author Alessandro Melandri (modified by)
     * */
    public class Tail {

      static long sleepTime = 1000;

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

        if (args.length > 0){

          if (args.length > 1)
        sleepTime = Long.parseLong(args[1]) * 1000;

          BufferedReader input = new BufferedReader(new FileReader(args[0]));
          String currentLine = null;

          while (true) {

        if ((currentLine = input.readLine()) != null) {
          System.out.println(currentLine);
          continue;
        }

        try {
          Thread.sleep(sleepTime);
        } catch (InterruptedException e) {
          Thread.currentThread().interrupt();
          break;
        }

          }
          input.close();

        } else {
          System.out.println("Missing parameter!\nUsage: java JavaTail fileName [updateTime (Seconds. default to 1 second)]");
        }
      }
    }
 

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X