New lines in a file

I'm trying to find a good way to get new lines in a file, and while this works it also uses 100% CPU and is driving me nuts. At least the profiler says this is .run is using the most, and taskmanager gives it 100%. The file name changes every day.

package net.st0rm.ss.loghandlers;

import java.io.*;

import java.util.ArrayList;

import java.util.Calendar;

import java.util.Timer;

import java.util.TimerTask;

import net.st0rm.ss.Log;

import net.st0rm.ss.gamecmdhandlers.GameCommandHandler;

import net.st0rm.ss.irc.IRC;

publicabstractclass LogHandler{

publicstatic ArrayList<GameCommandHandler> gameCmdHandlers =new ArrayList<GameCommandHandler>();

private BufferedReader reader =null;

private File directory =null;

private LogReadThread thread =null;

private String thisLine =null;

privateboolean skip =true;

/**

* Time to wait between reads

*/

private Long delay = 100;

/**

* Creates a new instance

* @param directory Directory of the files used

* @param skip Should the reader skip lines already existing?

*/

public LogHandler(File directory,boolean skip){

this.directory = directory;

this.skip = skip;

}

public String getFileName(){return"";};

privateclass LogReadThreadextends Thread{

publicboolean stop =false;

publicvoid run(){

Calendar c = Calendar.getInstance();

c.set(Calendar.HOUR_OF_DAY, 23);

c.set(Calendar.MINUTE, 59);

c.set(Calendar.SECOND,59);

StringBuilder sb =new StringBuilder(1000);

new Timer("Restart Timer").schedule(

new TimerTask(){

publicvoid run(){

try{

Thread.sleep(3000);

}catch (InterruptedException e){

// TODO Auto-generated catch block

e.printStackTrace();

}

IRC.getInstance().msg("Restarting reader \"" + this.getClass().getSimpleName() +"\" for the new day.");

LogHandler.this.restartReader();

}

}

,c.getTime(), 3600000*24);

try{

reader =new BufferedReader(new FileReader(directory.getAbsolutePath() +"/" + getFileName()));

if (skip)while ((reader.readLine()) !=null);

while (!stop){

try{

Thread.sleep(delay);

}catch (InterruptedException e){ System.out.println("Thread Interupted!");}

while ((sb.append(reader.readLine())).toString() !=null){ onNewLine(sb.toString()); sb.delete(0, sb.length());}

}

reader.close();

}catch (IOException e){

Log.log(e);

}

}

}

/**

* Call to re-start the file stream

*

*/

publicvoid restartReader(){

if (thread !=null) thread.stop =true;

thread =new LogReadThread();

thread.start();

}

/**

* Called when a new line is added to the file

* @param line The line added

*/

publicvoid onNewLine(String line){}

}

[6421 byte] By [aca20031a] at [2007-11-27 9:16:03]
# 1

Thread.sleep(100);

19:31:36 Sleep...

19:31:41 Sleep...

19:31:47 Sleep...

19:31:52 Sleep...

19:31:57 Sleep...

19:32:02 Sleep...

19:32:07 Sleep...

19:32:11 Sleep...

That could be one reason/cause. its sleeping every ~5 seconds, and I clearly say 0.1, so during the other 4.9 its stuck in the loop? Wtf?

I've changed it to:

while ((sb.append(reader.readLine())).toString() != null && !sb.toString().equals("")) { onNewLine(sb.toString()); sb.delete(0, sb.length()); }

aca20031a at 2007-7-12 22:05:37 > top of Java-index,Java Essentials,Java Programming...
# 2
What are you trying to accomplish, exactly?And why are you doing this:if (skip) while ((reader.readLine()) != null);
paulcwa at 2007-7-12 22:05:37 > top of Java-index,Java Essentials,Java Programming...
# 3
I'm trying to monitor log files, namely for this the log files of a game and parse the text. The skip line is because this is an abstract class * @param skip Should the reader skip lines already existing?
aca20031a at 2007-7-12 22:05:37 > top of Java-index,Java Essentials,Java Programming...
# 4
> The skip line> is because this is an abstract classThat makes no sense.
paulcwa at 2007-7-12 22:05:37 > top of Java-index,Java Essentials,Java Programming...
# 5
If the constructor has "true" as the second parameter, the line already in the file are not sent to onNewLine, if its false, they are.
aca20031a at 2007-7-12 22:05:37 > top of Java-index,Java Essentials,Java Programming...
# 6

The "skip" isn't the question. It's the

while ((reader.readLine()) != null);

If you want to move to arbitrary points in the file, maybe it would be better to use RandomAccessFile.

[add]

In particular, if you're concerned about it using too many cycles, then reading the file line-by-line when you just want to get to the end, may not be the best approach.

[/add]

But anyway...what exactly is your problem? Is it just the system load? Is it buggy? What?

Message was edited by:

paulcw

paulcwa at 2007-7-12 22:05:37 > top of Java-index,Java Essentials,Java Programming...
# 7
As i said, it uses 100% CPU. It works, and gives me the new lines, but uses a **** load of CPU. And the sleep line is only called every 5 seconds, if it helps figure out why.
aca20031a at 2007-7-12 22:05:37 > top of Java-index,Java Essentials,Java Programming...
# 8

I don't know what anybody can say other than "debug and profile your code".

It's weird that you have a Thread.sleep in the run method of a TimerTask. Why not just change the scheduling of the task?

This:

while ((sb.append(reader.readLine())).toString() != null) {

onNewLine(sb.toString());

sb.delete(0, sb.length());

}

(reindented to make it easier to read) is fishy. Even when you reach the end of reader's input, I think it will just loop forever. That's because appending null to a string buffer and calling toString results in the string "null", not the value null. So that while loop will never end.

Good luck.

paulcwa at 2007-7-12 22:05:37 > top of Java-index,Java Essentials,Java Programming...
# 9

This solution seems to work; apparantly checking if its ready makes it less anal :)

while (!stop) {

try {

Thread.sleep(100);

} catch (InterruptedException e) { System.out.println("Thread Interupted!"); }

if (reader.ready()) while ((line = reader.readLine()) != null) { onNewLine(line); }

aca20031a at 2007-7-12 22:05:38 > top of Java-index,Java Essentials,Java Programming...