Перенаправить консольный вывод в строку в Java - PullRequest
55 голосов
/ 03 января 2012

У меня есть одна функция, тип возврата которой равен VOID , и она печатается прямо на консоли.

Однако мне нужен этот вывод в строке, чтобы я мог работать с ним.

Поскольку я не могу вносить какие-либо изменения в функцию с типом возвращаемого значения VOID, я должен перенаправить этот вывод в строку.

Как я могу перенаправить его в JAVA?

Есть много вопросов, касающихся перенаправления stdout в строку, но они перенаправляют только ввод, полученный от пользователя, а не вывод какой-либо функции ...

Ответы [ 2 ]

100 голосов
/ 03 января 2012

Если функция печатает в 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!
20 голосов
/ 05 июня 2015

Вот утилита Class с именем ConsoleOutputCapturer.Это позволяет выводу перейти на существующую консоль, однако за сценой продолжает захватывать выводимый текст.Вы можете контролировать, что захватывать с помощью методов запуска / остановки.Другими словами, вызовите start, чтобы начать захват вывода консоли, и как только вы закончите захват, вы можете вызвать метод stop, который возвращает значение String, содержащее вывод консоли, для временного окна между вызовами start-stop.Этот класс не является потокобезопасным, хотя.

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