I am trying to read a log file continuously where the logs are being written ,both the processes are happening simultaneously.I am using rolling file appender for generating logs but the problem is ,when the file is about to change sometimes the data written when the file is nearing end is not read.Here is my code that generates log file continuously.
import java.util.Timer;
import java.util.TimerTask;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public final class Slf4jSample {
static Logger logger = LoggerFactory.getLogger(Slf4jSample.class);
public static void main(final String[] args) {
int delay = 0; // delay for 5 sec.
int period = 1000; // repeat every sec.
Timer timer = new Timer();
timer.scheduleAtFixedRate(new TimerTask() {
int i = 0;
public void run() {
// Task here ...
for (i = 0; i < 50; i++) {
logger.error("testing" + i);
System.out.println(i);
}
}
}, delay, period);
}
}
and here is my code that is reading it continuously.
import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.channels.FileChannel;
import java.nio.channels.FileLock;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Properties;
import java.util.Timer;
import java.util.TimerTask;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import com.mobility.config.ParseConfig;
import com.mobility.mail.SendMail;
import com.mobility.vo.ConfigurationVO;
import com.mobility.vo.LogVO;
import javax.mail.*;
TimerTask fileWatcherTask = new LogWatcher(fileName) {
long addFileLen = fileName.length();
FileChannel channel, oldChannel;
FileLock lock, oldLock;
@Override
protected void onChange(File file) {
RandomAccessFile access = null;
RandomAccessFile oldAccess = null;
int level = 0;
try {
access = new RandomAccessFile(file, "rw");
oldAccess = new RandomAccessFile(prevFileName, "rw");
channel = access.getChannel();
lock = channel.lock();
oldChannel = oldAccess.getChannel();
oldLock = oldChannel.lock();
// System.out.println("addFileLen>>" + addFileLen);
if (file.length() <= addFileLen) {
System.out.println("in if>>");
// reading old file
if (prevFileName.exists()) {
parsingLog(oldAccess, addFileLen,level);
addFileLen = file.length();
}
// reading old file ends
// Seek to 0th position when the file changes.
parsingLog(access, 0,level);
} else {
// access.seek(addFileLen);
parsingLog(access, addFileLen,level);
System.out.println("else>>>");
addFileLen = file.length();
}
} catch (Exception e) {
e.printStackTrace();
}
try {
lock.release();
oldLock.release();
} catch (IOException e1) {
e1.printStackTrace();
} // Close the file
try {
channel.close();
oldChannel.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
};
Timer timer = new Timer();
// repeat the check every second
long scheduleTimer = Long.parseLong(properties
.getProperty("scheduler.timer"));
timer.schedule(fileWatcherTask, new Date(), scheduleTimer);
}
}
public void parsingLog(RandomAccessFile access, long fileLength, int level) {
List<String> logList = new ArrayList<String>();
int flag = 0;
String line = null;
try {
access.seek(fileLength);
while ((line = access.readLine()) != null) {
System.out.println("after reading line >"+line);
}
}catch(Exception e){
}
}
PS:it doesn’t read the contents when it is nearing end.
I would open the file until it has been fully read and only close it when you have finished reading it. This may require your logger to create a new file each time, but you are unlikely to miss anything this way.