I'm trying to tie my PrintStream object to the console's output and error streams so that whatever I write there will also be written to my log file.
public static void tieOutputStreams(String fileName) {
try {
File output = new File(fileName);
FileWriter writer = new FileWriter(output);
writer.close();
outputStream = new TiedOutputStream(output);
}
catch (Exception e) {
e.printStackTrace();
}
System.setErr(outputStream);
System.setOut(outputStream);
}
Once I'm done writing, I could reset it back to the way things were.
public static void resetOutputStreams() {
outputStream.close();
System.setErr(System.err);
System.setOut(System.out);
}
TiedOutputStream class looks like this:
public class TiedOutputStream extends PrintStream {
public TiedOutputStream(File logFile) throws FileNotFoundException {
super(logFile);
}
@Override
public void print(Object obj) {
super.print(obj);
System.out.print(obj);
}
@Override
public PrintStream printf(String format, Object... args) {
super.printf(format, args);
System.out.printf(format, args);
return this;
}
@Override
public void println(Object args) {
super.println(args);
System.out.println(args);
}
}
And my main method:
public static void main(String[] args) {
try {
TieOutputStreams.tieOutputStreams("./sample.log");
System.out.println("Output console");
System.err.println("Error console");
float num = 1.123456f;
System.out.printf("A float: %.6f", num);
} catch (Exception e) {
e.printStackTrace();
}
finally {
TieOutputStreams.resetOutputStreams();
}
}
I want these statements to be printed on both my log file and the System consoles (out / err). For reasons I don't know, this isn't working. I appreciate all the answers and comments. Thanks in advance!
I know there is Log4j. But I want to do this anyway.
This doesn't work mainly because you didn't save the original System.out
and because you didn't override println(String obj)
When you call System.out.println("Output console");
you won't hit in the method you override because that one expects and object and there is a more specific method in PrintStream
that expects a String
argument
This seems to work:
public class TiedOutputStream extends PrintStream {
private final PrintStream sout;
private final PrintStream serr;
public TiedOutputStream(File logFile) throws FileNotFoundException {
super(logFile);
sout = System.out;//save standard output
serr = System.err;
}
@Override
public void print(Object obj) {
super.print(obj);
sout.print(obj);
}
@Override
public void println(String obj) {
super.println(obj);
sout.println(obj);
}
@Override
public PrintStream printf(String format, Object... args) {
super.printf(format, args);
sout.printf(format, args);
return this;
}
@Override
public void println(Object args) {
super.println(args);
sout.println(args);
}
}
Not sure why tieOutputStreams created that FileWriter
public static void tieOutputStreams(String fileName) {
try {
File output = new File(fileName);
outputStream = new TiedOutputStream(output);
System.setErr(outputStream);
System.setOut(outputStream);
} catch (Exception e) {
e.printStackTrace();
}
}
main
method remains the same. You should update resetOutputStreams to restore to original out
and err
. I would override all print* method from PrintStream
if I would use this.