Redirect console output to string in Java

113,704

Solution 1

If the function is printing to System.out, you can capture that output by using the System.setOut method to change System.out to go to a PrintStream provided by you. If you create a PrintStream connected to a ByteArrayOutputStream, then you can capture the output as a String.

Example:

// Create a stream to hold the output
ByteArrayOutputStream baos = new ByteArrayOutputStream();
PrintStream ps = new PrintStream(baos);
// IMPORTANT: Save the old System.out!
PrintStream old = System.out;
// Tell Java to use your special stream
System.setOut(ps);
// Print some output: goes to your special stream
System.out.println("Foofoofoo!");
// Put things back
System.out.flush();
System.setOut(old);
// Show what happened
System.out.println("Here: " + baos.toString());

This program prints just one line:

Here: Foofoofoo!

Solution 2

Here is a utility Class named ConsoleOutputCapturer. It allows the output to go to the existing console however behind the scene keeps capturing the output text. You can control what to capture with the start/stop methods. In other words call start to start capturing the console output and once you are done capturing you can call the stop method which returns a String value holding the console output for the time window between start-stop calls. This class is not thread-safe though.

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintStream;
import java.util.Arrays;
import java.util.List;

public class ConsoleOutputCapturer {
    private ByteArrayOutputStream baos;
    private PrintStream previous;
    private boolean capturing;

    public void start() {
        if (capturing) {
            return;
        }

        capturing = true;
        previous = System.out;      
        baos = new ByteArrayOutputStream();

        OutputStream outputStreamCombiner = 
                new OutputStreamCombiner(Arrays.asList(previous, baos)); 
        PrintStream custom = new PrintStream(outputStreamCombiner);

        System.setOut(custom);
    }

    public String stop() {
        if (!capturing) {
            return "";
        }

        System.setOut(previous);

        String capturedValue = baos.toString();             

        baos = null;
        previous = null;
        capturing = false;

        return capturedValue;
    }

    private static class OutputStreamCombiner extends OutputStream {
        private List<OutputStream> outputStreams;

        public OutputStreamCombiner(List<OutputStream> outputStreams) {
            this.outputStreams = outputStreams;
        }

        public void write(int b) throws IOException {
            for (OutputStream os : outputStreams) {
                os.write(b);
            }
        }

        public void flush() throws IOException {
            for (OutputStream os : outputStreams) {
                os.flush();
            }
        }

        public void close() throws IOException {
            for (OutputStream os : outputStreams) {
                os.close();
            }
        }
    }
}
Share:
113,704

Related videos on Youtube

SRK
Author by

SRK

Updated on July 05, 2022

Comments

  • SRK
    SRK almost 2 years

    I have one method whose return type is void and it prints directly on console.

    However I need that output in a String so that I can work on it.

    As I can't make any changes to the method with return type void I have to redirect that output to a String.

    How can I redirect it in Java?

  • user949300
    user949300 over 12 years
    Don't forget, when you are done, to call System.out.flush(), and then switch System.out back to the normal (or, more correctly, the previous) System.out. I see that @Ernest has added that into his code.
  • yshavit
    yshavit over 12 years
    Also, don't forget that this creates threading issues, not just for this method (which you could solve by synchronizing it) but for any other code that prints to stdout. baos.toString() could easily be "Foofohello worldofoo!"
  • Ernest Friedman-Hill
    Ernest Friedman-Hill almost 8 years
    @tuskiomi The string comes from ByteArrayOutputStream.toString() -- see last line of sample code.
  • mmierins
    mmierins almost 8 years
    Really nice solution, though I would suggest one little addition, call the close() method on baos stream in stop() method just before setting it to null to release all the resources.
  • Admin
    Admin over 7 years
    @ErnestFriedman-Hill :- I have a c utility which returns some value based on options. I executed this utility using java and the output is on the console, how to read this console echo output. there is no stream associated with the output. because I use a redirect to CON: ex:- util.exe -o CON: ( CON: for console output in DOS )
  • Raaj Lokanathan
    Raaj Lokanathan over 3 years
    Hi, what if the function is printing to c++ cout? Like for my case, my java application calls my c++ application methods thorough jni wrapper. Then how is this can be done @ErnestFriedman-Hill
  • Mistakamikaze
    Mistakamikaze about 3 years
    If I'm printing 3 times instead of 1, do I need to call System.out.flush 3 times?
  • Ernest Friedman-Hill
    Ernest Friedman-Hill about 3 years
    @Mistakamikaze Nope. Just right before you stop using the other stream.