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

SRK*_*SRK 56 java string console redirect stdout

我有一个函数,其返回类型是VOID,它直接在控制台上打印.

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

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

如何在JAVA中重定向?

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

Ern*_*ill 106

如果函数正在打印到System.out,则可以使用System.setOut更改方法捕获该输出System.out以转至PrintStream您提供的.如果创建PrintStream连接到a 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());
Run Code Online (Sandbox Code Playgroud)

该程序只打印一行:

Here: Foofoofoo!
Run Code Online (Sandbox Code Playgroud)

  • 另外,不要忘记这会产生线程问题,不仅仅是针对此方法(可以通过同步来解决),而是针对打印到stdout的任何其他代码.`baos.toString()`很容易成为"Foofohello worldofoo!" (5认同)
  • 完成后,请不要忘记调用System.out.flush(),然后将System.out切换回正常(或更准确地说,前一个)System.out.我看到@Ernest已将其添加到他的代码中. (4认同)

小智 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();
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 非常好的解决方案,尽管我建议添加一点,在 stop() 方法中调用 baos 流上的 close() 方法,然后将其设置为 null 以释放所有资源。 (2认同)