我正在试图找出如何连续读取文件,一旦添加了新行,就输出该行。我正在使用一个睡眠线程,但它似乎只是吹过整个文件并退出程序。
有什么建议我做错了吗?
这是我的代码:
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
提前致谢
更新:我已经改变了行“while(br.nextLine){”只是“while(TRUE){”
答案 0 :(得分:17)
这有些陈旧,但我使用了这种机制并且效果很好。
编辑:链接不再有效,但我在互联网档案中找到了它 https://web.archive.org/web/20160510001134/http://www.informit.com/guides/content.aspx?g=java&seqNum=226
诀窍是使用java.io.RandomAccessFile
,并定期检查文件长度是否大于当前文件位置。如果是,则读取数据。当你达到这个长度时,你会等待。洗,冲洗,重复。
我复制了代码,以防新链接停止工作
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();
}
}
}
答案 1 :(得分:6)
如果您计划在合理大小的应用程序上实现此功能,其中多个对象可能有兴趣处理进入该文件的新行,您可能需要考虑Observer模式。
从文件读取的对象将在处理完一行后立即通知订阅它的每个对象。 这将允许您在需要的类上保持逻辑分离。
答案 2 :(得分:2)
现在编写代码的方式,当你的'line == null'时你不会经历你的while循环,因为你在进入循环之前检查它是否有下一行。
相反,尝试执行while(true){ }
循环。这样,你将始终循环遍历它,捕捉你的暂停情况,直到你遇到一个会导致程序结束的情况。
答案 3 :(得分:2)
如果您不需要从头开始编写,请考虑org.apache.commons.io.input.Tailer。