Vis*_*was 2 java file-io process
有一个 shell 脚本正在更新日志文件。
我想在写入日志文件时逐行显示日志(而不是一次显示整个文件)。
写入文件工作正常,但我在读取文件时遇到问题,因为它一次显示整个文件。
这是我的阅读代码:
String nmapstatusfile = runMT.instdir+"/logs/nmapout."+customer+".log";
String nmapcommand=runMT.instdir+"/bin/doscan.sh "+nmapoutfile+" "
+IPRange+" "+nmapstatusfile+" "+nmapdonefile;
System.out.println("nmapcommand is .. "+nmapcommand);
Runtime r = Runtime.getRuntime();
Process pr = r.exec(nmapcommand);
RandomAccessFile raf =null;
try {
System.out.println(nmapstatusfile);
System.out.println("Reading a file");
raf = new RandomAccessFile(nmapstatusfile, "r");
} catch (FileNotFoundException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} // read from input file
System.out.println("Will print file contents line by line...");
long pos = 0;
raf.seek(pos);
String line =null;
while ((line = raf.readLine())!= null) {
System.out.println("in while loop for file read.");
System.out.println(line);
}
pos = raf.getFilePointer();
pr.waitFor();
Run Code Online (Sandbox Code Playgroud)
我已经使用了 RandomAccessFile,但是一直无法得到想要的结果。
我应该如何读取文件内容以便逐行显示?
这需要 Java 7,因为它在文件系统上注册了一个观察者,每当给定的文件发生变化时都会收到通知。它允许任意数量的读取器(使用同步来避免竞争条件)。
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.nio.file.ClosedWatchServiceException;
import java.nio.file.Path;
import java.nio.file.StandardWatchEventKinds;
import java.nio.file.WatchKey;
import java.nio.file.WatchService;
import java.util.ArrayDeque;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* Reads lines from a file that is actively being updated by another process
*/
public class Tailer {
private static final Logger logger = Logger.getLogger("Tailer");
private long tooLateTime = -1;
private final long maxMsToWait;
private final File file;
private long offset = 0;
private int lineCount = 0;
private boolean ended = false;
private WatchService watchService = null;
ArrayDeque<String> lines = new ArrayDeque<>();
/**
* Allows output of a file that is being updated by another process.
* @param file to watch and read
* @param maxTimeToWaitInSeconds max timeout; after this long without changes,
* watching will stop. If =0, watch will continue until <code>stop()</code>
* is called.
*/
public Tailer(File file, long maxTimeToWaitInSeconds) {
this.file = file;
this.maxMsToWait = maxTimeToWaitInSeconds * 1000;
}
/**
* Start watch.
*/
public void start() {
updateOffset();
// listens for FS events
new Thread(new FileWatcher()).start();
if (maxMsToWait != 0) {
// kills FS event listener after timeout
new Thread(new WatchDog()).start();
}
}
/**
* Stop watch.
*/
public void stop() {
if (watchService != null) {
try {
watchService.close();
} catch (IOException ex) {
logger.info("Error closing watch service");
}
watchService = null;
}
}
private synchronized void updateOffset() {
tooLateTime = System.currentTimeMillis() + maxMsToWait;
try {
BufferedReader br = new BufferedReader(new FileReader(file));
br.skip(offset);
while (true) {
String line = br.readLine();
if (line != null) {
lines.push(line);
// this may need tweaking if >1 line terminator char
offset += line.length() + 1;
} else {
break;
}
}
br.close();
} catch (Exception ex) {
logger.log(Level.SEVERE, "Error reading", ex);
}
}
/**
* @return true if lines are available to read
*/
public boolean linesAvailable() {
return ! lines.isEmpty();
}
/**
* @return next unread line
*/
public synchronized String getLine() {
if (lines.isEmpty()) {
return null;
} else {
lineCount ++;
return lines.removeLast();
}
}
/**
* @return true if no more lines will ever be available,
* because stop() has been called or the timeout has expired
*/
public boolean hasEnded() {
return ended;
}
/**
* @return next line that will be returned; zero-based
*/
public int getLineNumber() {
return lineCount;
}
private class WatchDog implements Runnable {
@Override
public void run() {
while (System.currentTimeMillis() < tooLateTime) {
try {
Thread.sleep(1000);
} catch (InterruptedException ex) {
// do nothing
}
}
stop();
}
}
private class FileWatcher implements Runnable {
private final Path path = file.toPath().getParent();
@Override
public void run() {
try {
watchService = path.getFileSystem().newWatchService();
path.register(watchService, StandardWatchEventKinds.ENTRY_MODIFY);
while (true) {
WatchKey watchKey = watchService.take();
if ( ! watchKey.reset()) {
stop();
break;
} else if (! watchKey.pollEvents().isEmpty()) {
updateOffset();
}
Thread.sleep(500);
}
} catch (InterruptedException ex) {
logger.info("Tail interrupted");
} catch (IOException ex) {
logger.log(Level.WARNING, "Tail failed", ex);
} catch (ClosedWatchServiceException ex) {
// no warning required - this was a call to stop()
}
ended = true;
}
}
/**
* Example main. Beware: the watch listens on a whole folder, not on a single
* file. Any update on a file within the folder will trigger a read-update.
* @param args
* @throws Exception
*/
public static void main(String[] args) throws Exception {
String fn = args.length == 0 ? "/tmp/test/log.txt" : args[0];
Tailer t = new Tailer(new File(fn), 10);
t.start();
while ( ! t.hasEnded()) {
while (t.linesAvailable()) {
System.out.println(t.getLineNumber() + ": " + t.getLine());
}
Thread.sleep(500);
}
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1897 次 |
| 最近记录: |