how to read back the lines printed out to the console?

F

frame

Hi:

We have an existing Java program, which prints out a lot of message
using System.out.println() method to the console. There are about 500
those calls in the code. We hope to add one more feature: besides
print out to the console as it is doing now, we also want to store
those messages in a text file. So the message will be in two places:
one place -- the console -- is shown the message progressively as the
program is running; another place -- a text file -- is created at the
end of the program.

Since there are about 500 calls in the code, we don't want to add a
duplicated printing method at every printing place. I am thinking to
let the program run as usal, printing out all the messages to the
console, then before the program ends, having a method reading in
every line on the console, which was printed out previously. I just
don't know how to achieve that.

Thank you very much.
 
G

glen herrmannsfeldt

frame said:
We have an existing Java program, which prints out a lot of message
using System.out.println() method to the console. There are about 500
those calls in the code. We hope to add one more feature: besides
print out to the console as it is doing now, we also want to store
those messages in a text file. So the message will be in two places:
one place -- the console -- is shown the message progressively as the
program is running; another place -- a text file -- is created at the
end of the program.

The old-fashioned way on unix is the tee command, which you can pipe
into, and will write to a file and stdout.

It should be easy to port to other systems with pipe, such as Windows.

-- glen
 
D

Daniel Pitts

Hi:

We have an existing Java program, which prints out a lot of message
using System.out.println() method to the console. There are about 500
those calls in the code. We hope to add one more feature: besides
print out to the console as it is doing now, we also want to store
those messages in a text file. So the message will be in two places:
one place -- the console -- is shown the message progressively as the
program is running; another place -- a text file -- is created at the
end of the program.

Since there are about 500 calls in the code, we don't want to add a
duplicated printing method at every printing place. I am thinking to
let the program run as usal, printing out all the messages to the
console, then before the program ends, having a method reading in
every line on the console, which was printed out previously. I just
don't know how to achieve that.

Thank you very much.
Perhaps System.out isn't the way to go. You might want to look into
logging frameworks, such as commons logging or log4j. They provide that
kind of flexibility and more.
 
A

Arne Vajhøj

We have an existing Java program, which prints out a lot of message
using System.out.println() method to the console. There are about 500
those calls in the code. We hope to add one more feature: besides
print out to the console as it is doing now, we also want to store
those messages in a text file. So the message will be in two places:
one place -- the console -- is shown the message progressively as the
program is running; another place -- a text file -- is created at the
end of the program.

Since there are about 500 calls in the code, we don't want to add a
duplicated printing method at every printing place. I am thinking to
let the program run as usal, printing out all the messages to the
console, then before the program ends, having a method reading in
every line on the console, which was printed out previously. I just
don't know how to achieve that.

If you can live with the file being written while the
program runs then something like:

import java.io.IOException;
import java.io_OutputStream;
import java.io.PrintStream;

public class TeeOutputStream extends OutputStream {
private OutputStream os1;
private OutputStream os2;
public TeeOutputStream(OutputStream os1, OutputStream os2) {
this.os1 = os1;
this.os2 = os2;
}
public void write(byte[] b) throws IOException {
os1.write(b);
os2.write(b);
}
public void write(byte[] b, int off, int len) throws IOException {
os1.write(b, off, len);
os2.write(b, off, len);
}
public void write(int b) throws IOException {
os1.write(b);
os2.write(b);
}
public void flush() throws IOException {
os1.flush();
os2.flush();
}
public void close() throws IOException {
os1.close();
os2.close();
}
public static void test2() {
System.out.println("This is test2");
}
public static void test1() {
System.out.println("This is test1");
}
public static void main(String[] args) throws IOException {
System.out.println("normal");
PrintStream sav = System.out;
System.setOut(new PrintStream(new TeeOutputStream(System.out, new
PrintStream("C:\\work\\tst.out"))));
test1();
test2();
System.setOut(sav);
System.out.println("normal");
}
}


Arne
 
A

Arne Vajhøj

Perhaps System.out isn't the way to go. You might want to look into
logging frameworks, such as commons logging or log4j. They provide that
kind of flexibility and more.

If it is a serious program, then that should be the way forward.

If it is a standalone SE app the jul could be an option too.

Arne
 
A

Arne Vajhøj

We have an existing Java program, which prints out a lot of message
using System.out.println() method to the console. There are about 500
those calls in the code. We hope to add one more feature: besides
print out to the console as it is doing now, we also want to store
those messages in a text file. So the message will be in two places:
one place -- the console -- is shown the message progressively as the
program is running; another place -- a text file -- is created at the
end of the program.

Since there are about 500 calls in the code, we don't want to add a
duplicated printing method at every printing place. I am thinking to
let the program run as usal, printing out all the messages to the
console, then before the program ends, having a method reading in
every line on the console, which was printed out previously. I just
don't know how to achieve that.

If you can live with the file being written while the
program runs then something like:

import java.io.IOException;
import java.io_OutputStream;
import java.io.PrintStream;

public class TeeOutputStream extends OutputStream {
private OutputStream os1;
private OutputStream os2;
public TeeOutputStream(OutputStream os1, OutputStream os2) {
this.os1 = os1;
this.os2 = os2;
}
public void write(byte[] b) throws IOException {
os1.write(b);
os2.write(b);
}
public void write(byte[] b, int off, int len) throws IOException {
os1.write(b, off, len);
os2.write(b, off, len);
}
public void write(int b) throws IOException {
os1.write(b);
os2.write(b);
}
public void flush() throws IOException {
os1.flush();
os2.flush();
}
public void close() throws IOException {
os1.close();
os2.close();
}
public static void test2() {
System.out.println("This is test2");
}
public static void test1() {
System.out.println("This is test1");
}
public static void main(String[] args) throws IOException {
System.out.println("normal");
PrintStream sav = System.out;
System.setOut(new PrintStream(new TeeOutputStream(System.out, new
PrintStream("C:\\work\\tst.out"))));
test1();
test2();
System.setOut(sav);
System.out.println("normal");
}
}

If you don't like that approach, then maybe look at some
AspectJ magic.

Arne
 
A

Arne Vajhøj

I missed that requirement. It might be possible to do this
in a thread set with

I somewhat expect that this requirement is not something OP needs
but something that was written because OP thought it should be
done by reading from the console at then end of the run.

Arne
 
A

Arne Vajhøj

Seems likely, and I hope that is the case.

It could be stashed away in a ByteArrayOutputStream
and written to file later, but it seems so pointless.

Arne
 
F

frame

Thank you very much for all the replies. Probably I didn't explain my
question clear. After reading all the replies, I am sorry I still
didn't get the idea to proceed.

My problem is such: our finished Java program has many printing
statements, e.g.

System.out.println("step A: everything is ok");
....
System.out.println("step B: computation starts now");
....

if(so)
{
System.out.println("warning: temperature is too hot");
}

There are about 500 of those. When we run the program, all these
messages show up on the console -- that's good. But now, we also want
to keep those messages in a file. I have two ideas, but none of them
is acceptable:

1)at the beginning of the program, I added a little piece of code(re-
direct the System output to a file), now all the existing 500
System.out.println(..) prints to a file, not the console any more --
this is not good, because the program runs up to 5 hours, we hope to
see the message progressively on the console. With this approach, we
have to wait till the program finished and open the text file to read.
2)another approach, use log4j to replace those 500 printing statements
-- we are not ready for this approach right now, because there are 500
of them -- in many classes. log4j has different levels(INFO, WARNING,
ERROR etc). We need to analyze every printing case to decide its
level. It is a too big approach for now.

Ideally, I was wondering if this is possible: at the end of the
program, when all those messages have been printed out to the console,
I can added a small piece of code, which will read all the lines on
the console back, then write them into a text file. I don't know if
this makes sense.
 
A

Arne Vajhøj

Thank you very much for all the replies. Probably I didn't explain my
question clear. After reading all the replies, I am sorry I still
didn't get the idea to proceed.

My problem is such: our finished Java program has many printing
statements, e.g.

System.out.println("step A: everything is ok");
...
System.out.println("step B: computation starts now");
...

if(so)
{
System.out.println("warning: temperature is too hot");
}

There are about 500 of those. When we run the program, all these
messages show up on the console -- that's good. But now, we also want
to keep those messages in a file. I have two ideas, but none of them
is acceptable:

1)at the beginning of the program, I added a little piece of code(re-
direct the System output to a file), now all the existing 500
System.out.println(..) prints to a file, not the console any more --
this is not good, because the program runs up to 5 hours, we hope to
see the message progressively on the console. With this approach, we
have to wait till the program finished and open the text file to read.
2)another approach, use log4j to replace those 500 printing statements
-- we are not ready for this approach right now, because there are 500
of them -- in many classes. log4j has different levels(INFO, WARNING,
ERROR etc). We need to analyze every printing case to decide its
level. It is a too big approach for now.

Ideally, I was wondering if this is possible: at the end of the
program, when all those messages have been printed out to the console,
I can added a small piece of code, which will read all the lines on
the console back, then write them into a text file. I don't know if
this makes sense.

So far you have not explained why the proposed solution of
System.setOut to a PrintStream that writes to both console and
file does not work.

Arne
 
S

Stefan Ram

frame said:
console, then before the program ends, having a method reading in
every line on the console, which was printed out previously. I just

To actually »read back from the console«, one can built a
Java console using Swing, placing a JTextArea into a
JScrollPane. One then indeed is at liberty to implement this
console in such a manner that one also can read from it.
 
R

Roedy Green

Ideally, I was wondering if this is possible: at the end of the
program, when all those messages have been printed out to the console,
I can added a small piece of code, which will read all the lines on
the console back, then write them into a text file. I don't know if
this makes sense.

For one project, I wrote a console logger that used a GUI and a
JTable. It let you scroll back and forth over the entire log while it
was running. It also let me have a quite fancy log with colours,
icons and items that faded over time.

Another one had a "log" that was kept sorted with the most important
things to notice at the top.
 
L

Lew

Thank you very much for all the replies. Probably I didn't explain my
question clear. After reading all the replies, I am sorry I still
didn't get the idea to proceed.

My problem is such: our finished Java program has many printing
statements, e.g.

System.out.println("step A: everything is ok");
...
System.out.println("step B: computation starts now");
...

if(so)
{
System.out.println("warning: temperature is too hot");
}

There are about 500 of those. When we run the program, all these
messages show up on the console -- that's good. But now, we also want
to keep those messages in a file. I have two ideas, but none of them
is acceptable:

1)at the beginning of the program, I added a little piece of code(re-
direct the System output to a file), now all the existing 500
System.out.println(..) prints to a file, not the console any more --
this is not good, because the program runs up to 5 hours, we hope to
see the message progressively on the console. With this approach, we
have to wait till the program finished and open the text file to read.
2)another approach, use log4j to replace those 500 printing statements
-- we are not ready for this approach right now, because there are 500
of them -- in many classes. log4j has different levels(INFO, WARNING,
ERROR etc). We need to analyze every printing case to decide its
level. It is a too big approach for now.

Ideally, I was wondering if this is possible: at the end of the
program, when all those messages have been printed out to the console,
I can added a small piece of code, which will read all the lines on
the console back, then write them into a text file. I don't know if
this makes sense.

People have already answered this question in detail, with code examples.

But what you really need to do is take the suggestion to use a logging
framework. Then you can change the configuration in a properties file with no
code changes. 500 instances isn't very many, especially with a global
's/System.out.println/logger.info/'. Any decent IDE will let you do that in a
single pop.

Do that. Really. It's the right thing to do.
 
J

Jukka Lahtinen

frame said:
1)at the beginning of the program, I added a little piece of code(re-
direct the System output to a file), now all the existing 500
System.out.println(..) prints to a file, not the console any more --
this is not good, because the program runs up to 5 hours, we hope to
see the message progressively on the console. With this approach, we
have to wait till the program finished and open the text file to read.

Can't you use tail -f on another console (or equivalent for windows)?

And of course, other people have suggested replacing System.out with a
stream that prints to both console and a file.
However, redirecting the output and reading the file simultaneously with
tail might be possible without even recompiling the program.
 
F

frame

Wow. Thank you so much. I greatly appreciate your effort for putting
up such complete and nicely formatted code, including testing code.
Thank you very very much.

Like Patricia said, I am almost there. Based on your code, my class
ends up to be:

class TeeOutputStream extends OutputStream
{
private final OutputStream os1;
// private final OutputStream os2;
private final Logger _logger; //the class of Logger is our own
class

public TeeOutputStream(final OutputStream os1, final Logger log)
{
this.os1 = os1;
// this.os2 = os2;
this._logger = log;
}

@Override
public void write(final byte[] b) throws IOException
{
os1.write(b);
// os2.write(b);
this._logger.log(Logger.INFO, new String(b));
}

@Override
public void write(final byte[] b, final int off, final int len)
throws IOException
{
os1.write(b, off, len);
// os2.write(b, off, len);
this._logger.log(Logger.INFO, new String(b, off, len));
}

@Override
public void write(final int b) throws IOException
{
os1.write(b);
// os2.write(b);
this._logger.log(Logger.INFO, String.valueOf((char)b));
}

@Override
public void flush() throws IOException
{
os1.flush();
// os2.flush();
}

@Override
public void close() throws IOException
{
os1.close();
this._logger.close();
}
}

At the place of calling this class,

final TeeOutputStream teeOutputStream = new
TeeOutputStream(System.out, logger);

System.setOut(new PrintStream(teeOutputStream));

Since now, all System.out.println(..) message is shown on the console
progressively when the program running and be saved into a file at the
end by writing out our logger object to a xml file.

Thank you again for all the help.
 
L

Lew

Wow. Thank you so much. I greatly appreciate your effort for putting
up such complete and nicely formatted code, including testing code.
Thank you very very much.

Like Patricia said, I am almost there. Based on your code, my class
ends up to be:

class TeeOutputStream extends OutputStream
{ ....

Since now, all System.out.println(..) message is shown on the console
progressively when the program running and be saved into a file at the
end by writing out our logger object to a xml file.

Thank you again for all the help.

This is still far harder, more fragile and less flexible that biting the
bullet and *using a logging framework*.

In your career you will have to learn when to do the right thing. Doing the
wrong thing, although you believe it now to be more expedient, will inevitably
bite you in the ass. Hopefully at that time you'll say to yourself, "Well, Lew
warned me this was going to happen. I should have listened back then when it
was only a simple matter of substituting text in 500 locations instead of
having to maintain this kludgey, buggy, large subsystem."
 
L

Lew

Can't you use tail -f on another console (or equivalent for windows)?

And of course, other people have suggested replacing System.out with a
stream that prints to both console and a file.
However, redirecting the output and reading the file simultaneously with
tail might be possible without even recompiling the program.

Or he could use the actual 'tee' command as suggested upstream. Or he could do
the right thing and drop the stupid 'System.out' logging and use a real
logging framework. ONE COMES WITH JAVA for Pete's sake!
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,744
Messages
2,569,483
Members
44,901
Latest member
Noble71S45

Latest Threads

Top