How do you continuously read a file in Java?

▼魔方 西西 提交于 2019-11-30 08:06:25

问题


I'm trying to figure out how to continuously read a file and once there is a new line added, output the line. I'm doing this using a sleep thread however it just seems to blow through the whole file and exit the program.

Any suggestions what I'm doing wrong?

Here is my code:

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 

thanks in advance

UPDATE: I've since changed the line "while (br.nextLine ) {" to just "while (TRUE) {"


回答1:


This in somewhat old, but I have used the mechanism and it works pretty well.

edit: link no longer works, but I found it in the internet archive https://web.archive.org/web/20160510001134/http://www.informit.com/guides/content.aspx?g=java&seqNum=226

The trick is to use a java.io.RandomAccessFile, and periodically check if the file length is greater that your current file position. If it is, then you read the data. When you hit the length, you wait. wash, rinse, repeat.

I copied the code, just in case that new link stops working

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



回答2:


If you're planning to implement this on a reasonable sized application where multiple objects might be interested in processing the new lines coming to the file, you might want to consider the Observer pattern.

The object reading from the file will notify each object subscribed to it as soon as a line has been processed. This will allow you to keep logic well separated on the class where it's needed.




回答3:


The way your code is written now, you will not go through your while loop when your 'line==null' because you are checking to see that it has a next line before you even get into the loop.

Instead, try doing a while(true){ } loop. That way, you will always be looping through it, catching your pause cases, until you hit a condition that would cause the program to end.




回答4:


Also consider org.apache.commons.io.input.Tailer if you do not have the requirement of writing this from scratch.



来源:https://stackoverflow.com/questions/2210975/how-do-you-continuously-read-a-file-in-java

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!