将控制台输出重定向到java中的字符串

时间:2012-01-03 05:34:43

标签: java string redirect console stdout

我有一个返回类型为VOID 的函数,它直接在控制台上打印。

但是我需要输出字符串,以便我可以处理它。

由于我无法使用返回类型的函数进行任何更改是VOID所以我必须将该输出重定向到字符串。

如何在JAVA中重定向?

关于将stdout重定向到字符串有很多问题,但是它们仅重定向来自用户的输入而不是某些函数的输出......

3 个答案:

答案 0 :(得分:98)

如果该功能正在打印到System.out,您可以使用System.setOut方法更改System.out以转到您提供的PrintStream来捕获该输出。如果您创建了与PrintStream相关联的ByteArrayOutputStream,那么您可以将输出捕获为String

示例:

// 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());

此程序只打印一行:

Here: Foofoofoo!

答案 1 :(得分:19)

这是一个名为ConsoleOutputCapturer的实用程序类。它允许输出转到现有控制台,但是在场景后面继续捕获输出文本。您可以使用start / stop方法控制要捕获的内容。换句话说,调用start开始捕获控制台输出,一旦完成捕获,就可以调用stop方法,该方法返回一个String值,该值保存控制台输出,用于启动 - 停止调用之间的时间窗口。这个类虽然不是线程安全的。

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();
            }
        }
    }
}

答案 2 :(得分:0)

虽然这个问题很老而且已经有很好的答案,但我想提供一个替代方案。我专门为此用例创建了一个库。它名为 Console Captor,您可以使用以下代码段添加它:

<dependency>
    <groupId>io.github.hakky54</groupId>
    <artifactId>consolecaptor</artifactId>
    <version>1.0.0</version>
    <scope>test</scope>
</dependency>

示例类

public class FooService {

    public void sayHello() {
        System.out.println("Keyboard not responding. Press any key to continue...");
        System.err.println("Congratulations, you are pregnant!");
    }

}

单元测试

import static org.assertj.core.api.Assertions.assertThat;

import nl.altindag.console.ConsoleCaptor;
import org.junit.jupiter.api.Test;

public class FooServiceTest {

    @Test
    public void captureStandardAndErrorOutput() {
        ConsoleCaptor consoleCaptor = new ConsoleCaptor();

        FooService fooService = new FooService();
        fooService.sayHello();

        assertThat(consoleCaptor.getStandardOutput()).contains("Keyboard not responding. Press any key to continue...");
        assertThat(consoleCaptor.getErrorOutput()).contains("Congratulations, you are pregnant!");
        
        consoleCaptor.close();
    }
}