简体   繁体   中英

How to tie a PrintStream to the System.out and err streams

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM