Redirect console output to string in Java
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!
System.out to string
Even if not the best idea, one solution could be:
public static void main(String[] xxx) {
System.setOut(new DoublePrintStream(System.out, "/myfile.txt"));
System.setErr(new DoublePrintStream(System.err, "/errors.txt"));
System.out.println("this works");
try { throw new RuntimeException("oulala");} catch(Exception e) { e.printStackTrace(); }
//System.out.close(); // maybe required at the end of execution
}
class DoublePrintStream extends PrintStream {
private final OutputStream fos;
DoublePrintStream(OutputStream out, String filename){
super(out);
try {
fos = new FileOutputStream(new File(filename));
} catch (FileNotFoundException e) {
throw new AssertionError("cant create file", e);
}
}
@Override
public void write(byte[] buf, int off, int len) {
super.write(buf, off, len);
try {
fos.write(buf, off, len);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
@Override
public void close() {
try {
fos.close();
} catch (IOException e) {
throw new RuntimeException(e);
} finally {
super.close();
}
}
}
so you have output in the console + in a file, and all errors in a separate file.
Even if logging frameworks are way better, this solution has the advantage to require no code change at all.
PS: in a multithreaded context, you should also synchronize the methods of DoublePrintStream
How to capture all system.out.println to an array or list of string
System.out.println
method has print
and newLine
methods. There is no way to capture only System.out.println
method, you should capture all System.out.print
methods with changing System.out
variable.
System.out.println
jdk implementation:
public void println(String x) {
synchronized (this) {
print(x);
newLine();
}
}
Text collector output stream class for capturing System.out.print
content:
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;
public class TextCollector extends OutputStream {
private final List<String> lines = new ArrayList<>();
private StringBuilder buffer = new StringBuilder();
@Override
public void write(int b) throws IOException {
if (b == '\n') {
lines.add(buffer.toString());
buffer = new StringBuilder();
} else {
buffer.append((char) b);
}
}
public List<String> getLines() {
return lines;
}
}
Example test implementation:
import java.util.*;
import java.io.*;
public class Main {
public static void main(String[] args) {
// store current output
PrintStream tmpOut = System.out;
// change stream into text collector
TextCollector textCollector = new TextCollector();
System.setOut(new PrintStream(textCollector));
// collect lines
System.out.println("Test-1");
System.out.println("Test-2");
// print lines to console
System.setOut(tmpOut);
List<String> lines = textCollector.getLines();
for (String line : lines) {
System.out.println(line);
}
}
}
Redirect stdout to a string in Java
Yes - you can use a ByteArrayOutputStream
:
ByteArrayOutputStream baos = new ByteArrayOutputStream();
System.setOut(new PrintStream(baos));
Then you can get the string with baos.toString()
.
To specify encoding (and not rely on the one defined by the platform), use the PrintStream(stream, autoFlush, encoding)
constructor, and baos.toString(encoding)
If you want to revert back to the original stream, use:
System.setOut(new PrintStream(new FileOutputStream(FileDescriptor.out)));
Redirecting console output to GUI
You need to invoke startMeUp
in a new thread, because your console program is blocking the event dispatch thread. Like this:
new Thread () {
@Override public void run () {
GreenhouseControls.startMeUp();
}
}.start();
instead of just
GreenhouseControls.startMeUp();
I want to save eclipse console log into a string
You can redirect console output to file in run configuration settings on the "Common" tab.
Java/Kotlin way to redirect command output to both stdout and String
Here is the ProcessBuilder solution, which I initially wanted to avoid. It does the job though it is bulky. Let me know if a better API is made available!
var logs:String = ""
runCatching {
var command:List<String> = listOf("command", "arg")
parameters.params?.let {command += it} // dynamic args
ProcessBuilder(command)
.directory(File(scriptRoot))
.redirectOutput(ProcessBuilder.Redirect.PIPE)
.redirectErrorStream(true) // Merges stderr into stdout
.start().also { process ->
withContext(Dispatchers.IO) { // More info on this context switching : https://elizarov.medium.com/blocking-threads-suspending-coroutines-d33e11bf4761
launch {
process.inputStream.bufferedReader().run {
while (true) { // Breaks when readLine returns null
readLine()?.let { line ->
logger.trace(line) // realtime logging
logs += "$line\n" // record
} ?: break
}
}
}
process.waitFor(60, TimeUnit.MINUTES)
if(process.isAlive) {
logs += "TIMEOUT occurred".also { logger.warn(it) } + "\n"
process.destroy()
}
}
}
}.onSuccess { process ->
if(process.exitValue() == 0) {
// completed with success
} else {
// completed with failure
}
}.onFailure { ex ->
logs = ex.stackTraceToString()
}
// Logs are available in $logs
Related Topics
Change Background Color of Single Specific Menu Items of Navigationview
Retrofit2 Android: Expected Begin_Array But Was Begin_Object at Line 1 Column 2 Path $
Unexpected Top-Level Exception: Com.Android.Dex.Dexexception: Multiple Dex Files Define
Java Program That Runs Commands with Linux Terminal
Hibernate: Different Object with the Same Identifier Value Was Already Associated with the Session
Why Does Hibernate Require No Argument Constructor
Parsing an Arithmetic Expression and Building a Tree from It in Java
What Is the Main Difference Between Inheritance and Polymorphism
Jpql Create New Object in Select Statement - Avoid or Embrace
Run Piece of Code Contained in a String
Gradle - What Is a Non-Zero Exit Value and How to Fix It
Recyclerview Item Click Listener the Right Way
Countdowntimer in Minutes and Seconds
How to Achieve Javafx Mouse Event "Push and Hold"
Expected Begin_Array But Was Begin_Object at Line 1 Column 2