Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Copy STDOUT to file without stopping it showing onscreen

The program I am making is designed to be run unattended, because of this I have redirected the stdout and stderr streams to a log file. While this works without any problems, while I am still making and debugging the software I would like it to show on the screen as well. Is this possible?

To redirect the streams I have used

System.setErr(logWriter);
System.setOut(logWriter);

Thanks.

like image 611
A Jackson Avatar asked Dec 01 '22 07:12

A Jackson


2 Answers

Yes. Logging frameworks (i.e. log4j) are best, isDebugMode is handy in a development environment but if you really need to "tee" your stdout you can like so.

import java.io.PrintStream;
import java.io.File;
public class TeeStream extends PrintStream {
    PrintStream out;
    public TeeStream(PrintStream out1, PrintStream out2) {
        super(out1);
        this.out = out2;
    }
    public void write(byte buf[], int off, int len) {
        try {
            super.write(buf, off, len);
            out.write(buf, off, len);
        } catch (Exception e) {
        }
    }
    public void flush() {
        super.flush();
        out.flush();
    }
}

http://www.exampledepot.com/egs/java.lang/Redirect.html

// import java.io.FileOutputStream;
String dateString = new SimpleDateFormat("yyyyMMdd").format(new Date());
File logFile = new File("mylogfile_" + dateString +".log");
PrintStream logOut = new PrintStream(new FileOutputStream(logFile, true));

PrintStream teeStdOut = new TeeStream(System.out, logOut);
PrintStream teeStdErr = new TeeStream(System.err, logOut);

System.setOut(teeStdOut);
System.setErr(teeStdErr);

You'll soon find LOG.somelevel(msg) much more manageable than System.out.println(msg). It is great to raise the log level when things are working well and lower the level when they aren't without deploying a debug build.

like image 103
KCD Avatar answered Dec 03 '22 20:12

KCD


a bit crude perhaps, but you could try this:

private static final isDebugMode = true;

...

if (!isDebugMode) {
  System.setErr(logWriter);
  System.setOut(logWriter);
} 

Alternatively you could write your own PrintStream implementation which simultaneously writes to both your log file and the screen. It doesn't sound like you need this behaviour except in development though so the latter whilst actually a more accurate answer to your question is probably not what you actually want.

like image 30
Robin Avatar answered Dec 03 '22 21:12

Robin