两种方式,可以实现linux的“tail -f”命令。
1、FileInputStream在读取文件内容的时候,其他外部工具(如记事本、notepad++等)可以同时进行写入,且写入内容能继续读取到。
因此,利用该接口,或经封装后的BufferedReader等接口,即可实现。
参考代码:
String srcFilename = "E:\\tmp2\\1.log";
String charset = "GBK";
InputStream fileInputStream = new FileInputStream(srcFilename);
fileInputStream.skip(10); // skip n bytes
Reader fileReader = new InputStreamReader(fileInputStream, charset);
BufferedReader bufferedReader = new BufferedReader(fileReader);
String singleLine;
while(true){
if( (singleLine = bufferedReader.readLine()) != null ){
System.out.println(singleLine);
continue;
}
try {
Thread.sleep(1000L);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
break;
}
}
bufferedReader.close();
利用while(true)循环,实现tail命令的-f功能,读取后续写入的内容。
该代码中,没有判断文件被清空的情况(文件内容被全部删除了,但文件还 在,即“文件大小变小了”这种情况)。要处理这种情况,需要在while循环中判断文件大小是否变小,如果是,则需要从头开始读取(重新创建reader对象)
String srcFilename = "E:\\tmp2\\1.txt";
String charset = "GBK";
File file = new File(srcFilename);
InputStream fileInputStream = new FileInputStream(srcFilename);
fileInputStream.skip(1); // skip n bytes if needed, filesystem may position to the offset directly but not read really.
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(fileInputStream, charset));
String singleLine;
long fileSize = file.length();
while (true) {
try {
if ((singleLine = bufferedReader.readLine()) != null) {
System.out.println(singleLine);
fileSize = Math.max(file.length(), fileSize);
continue;
}
} catch (IOException e) { // 文件被清空的时候FileInputStream会被close
bufferedReader = new BufferedReader(new InputStreamReader(new FileInputStream(srcFilename), charset));
fileSize = file.length();
}
try {
if (file.length() < fileSize) { // 文件被清空了
bufferedReader.close();
bufferedReader = new BufferedReader(new InputStreamReader(new FileInputStream(srcFilename), charset));
fileSize = file.length();
}
Thread.sleep(1000L);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
bufferedReader.close();
break;
}
}
2、利用RandomAccessFile,在代码中记录文件先前的大小,定时查看文件大小是否发生变化,如果是,则读取新的内容部分(利用RandomAccessFile的seek方法跳过之前已经读取的内容)。
参考代码:http://www.verydemo.com/demo_c89_i23598.html