Tuesday, April 8, 2008

How to redirect System.out.println in Java

Did you ever get frustrated with a codebase which has overuse of System.out.println??
May be it is flooding your console or even worse you need to capture the outputs to analyze them....Ever wondered how you can capture your System.out.println() 's of your tomcat application?? Well, you can always use IO Redirect in unix to send the output to a file. You can use find replace to change all System.out.println() to some method call which will write the logs to a file. But being the lazy programmer that I am, I always look for a shortcut. And sometimes I even find one :)
I was working with this code and it had important System.out.println everywhere. I wanted to use trail/grep and stuffs like that with the console logs but I couldn't do that on the application console. So this is what I did to redirect all System.out.println to a log file.

public class MyMainClass {
public static void main(String[] args) throws FileNotFoundException {

File file = new File("/home/sajid/sysout.log");
PrintStream printStream = new PrintStream(new FileOutputStream(file));

System.out.println("1");

System.setOut(printStream);


System.out.println("2");

}
}


Did you ever notice that System.out is just another PrintStream and you can replace it with your own? This is why I love java. You can replace many things with your own implementation. Did I tell you how I replaced the URLClassLoader with my JDBCClassLoader to load classes from Database? Lets keep that story for another post.

16 comments:

Unknown said...

hi sajid,
the blog proved really useful to me,
nice work

Anonymous said...

How do you set it back to write to the console?

Sajid said...

@Dayl:

Quick trick is to save the previous System.out into some static variable/cache before you change it. For example:

PrintStream realSystemOut = System.out;

now set it back like this:

System.setOut(realSystemOut);

It should work.

Anonymous said...

thans a lot man.........seriously thanks a lot
it had saved my life i was running in a last min project submission and had to convert more than 100 .out.println to save to file in less than 5 mins and this proved very helful thanks a ton...

Sajid said...

Glad to know it helped :)

Anonymous said...

Really a quick solution ... and WORKING! Thank you!

Unknown said...

great work sajid!!
I'm new to java language and I'm really grateful to you and to your blog :) I'm working on an orbital propagator and I needed a simple way to redirect my output on a text file. Thank you SO MUCH!

Daniel said...

Thanks mate! Was just trying to work out how to redirect all of my System.out commands to a text file for processing later, that just saved me a lot of time!

Daniel said...
This comment has been removed by the author.
Barbara said...

Thanks a lot, works perfectly fine!

Rob said...

thank you!!

Roberto

Bar said...

Very useful. Thank you!

swathija said...

Hello Sajid,
I tried to right my existing log file with the following code snippet. It doesn't seem to append in my log code.


private void logToSystemOut(SOAPMessageContext smc) {
Boolean outboundProperty = (Boolean)
smc.get (MessageContext.MESSAGE_OUTBOUND_PROPERTY);

if (outboundProperty.booleanValue()) {
out.println("\nOutbound message:");
} else {
out.println("\nInbound message:");
}

SOAPMessage message = smc.getMessage();
try {
message.writeTo(out);
out.println(""); // just to add a newline
System.setOut(new PrintStream(new LoggerStream(Logger.getLogger("DEBUG"), Level.INFO, out)));
} catch (Exception e) {
logger.info(e.getLocalizedMessage());
out.println("Exception in handler: " + e);
}
}


LoggerStream:

package com.scotiabank.ebss.idm.util;

import java.io.IOException;
import java.io.OutputStream;

import org.apache.log4j.Level;
import org.apache.log4j.Logger;

public class LoggerStream extends OutputStream
{
private final Logger logger;
private final Level logLevel;
private final OutputStream outputStream;

public LoggerStream(Logger logger, Level logLevel, OutputStream outputStream)
{
super();

this.logger = logger;
this.logLevel = logLevel;
this.outputStream = outputStream;
}

@Override
public void write(byte[] b) throws IOException
{
outputStream.write(b);
String string = new String(b);
if (!string.trim().isEmpty())
logger.log(logLevel, string);
}

@Override
public void write(byte[] b, int off, int len) throws IOException
{
outputStream.write(b, off, len);
String string = new String(b, off, len);
if (!string.trim().isEmpty())
logger.log(logLevel, string);
}

@Override
public void write(int b) throws IOException
{
outputStream.write(b);
String string = String.valueOf((char) b);
if (!string.trim().isEmpty())
logger.log(logLevel, string);
}
}

Ben said...

Thanks! Just what I was looking for!

Tiyah said...

Feel obliged to say a big thanks. Exactly what I was looking. And I'm wondering if it's possible to both print out in the console and in a log file... (just in case)
Thanks again!

Java Experience said...

This is useful for those preparing for java interviews. thanks for sharing.
Some more tips contributed by me like how to remove sysout from your code in Eclipse