Reputation: 1
i am working on a selfmade console (API, with GUI) and wanted to transfer the output from a program A, using my console, to my console class B, then read a string from it (the output from program A).
All answers i found were about creating a new PrintStream around a ByteArrayOutputStream etc.
The reason why i want to do this, is because i want to keep the code as easy as possible for others (best solution: one method to call in the program,).
It would be great if something like this would be possible for the programmer using my API:
ConsoleAPI c = new ConsoleAPI();
c.setOutput(System.out);
System.out.println("Hello World!");
I don't think, this is possible, but maybe it is. :)
Thanks in advance!
Upvotes: 0
Views: 294
Reputation: 14159
Here is some code I once wrote to redirect System streams. Basically, calling ConsoleHandler.redirectSystemStreams()
will give you an instance of ConsoleHandler
that you can add listeners to. The listeners will be called when new output is available.
Hope that helps to get you started.
ConsoleHandler
package com.dua3.util.io;
import java.io.ByteArrayOutputStream;
import java.io.Closeable;
import java.io.IOException;
import java.io.PrintStream;
import java.util.LinkedList;
import java.util.List;
public class ConsoleHandler implements Closeable {
public static final int SYSTEM_OUT = 1;
public static final int SYSTEM_ERR = 2;
public static final int COPY_TO_SYSTEM_OUT = 8;
protected final ByteArrayOutputStream outBytes;
protected final PrintStream out;
protected final List<ConsoleListener> consoleListeners;
public synchronized static ConsoleHandler redirectSystemStreams(int what) {
final PrintStream oldSystemOut = System.out;
final PrintStream oldSystemErr = System.err;
final boolean copyToSystemOut = (what & COPY_TO_SYSTEM_OUT) != 0;
final boolean redirectSystemOut = (what & SYSTEM_OUT) != 0;
final boolean redirectSystemErr = (what & SYSTEM_ERR) != 0;
ConsoleHandler consoleHandler = new ConsoleHandler() {
@Override
public void close() throws IOException {
// check state
if (redirectSystemOut && System.out != this.out) {
throw new IOException("System.out was redirected and can not be restored!");
}
if (redirectSystemErr && System.err != this.out) {
throw new IOException("System.err was redirected and can not be restored!");
}
// restore System Streams
if (redirectSystemOut) {
System.setOut(oldSystemOut);
}
if (System.err == this.out) {
System.setErr(oldSystemErr);
}
// call super implementation
super.close();
}
@Override
protected void contentChanged(String data) {
super.contentChanged(data);
if (copyToSystemOut) {
oldSystemOut.append(data);
}
}
};
// redirect streams to console handler
if (redirectSystemOut) {
System.setOut(consoleHandler.getOut());
}
if (redirectSystemErr) {
System.setErr(consoleHandler.getOut());
}
return consoleHandler;
}
public ConsoleHandler() {
this.consoleListeners = new LinkedList<ConsoleListener>();
this.outBytes = createByteStream();
this.out = createOutputStream();
}
private ByteArrayOutputStream createByteStream() {
return new ByteArrayOutputStream(256) {
@Override
public void flush() throws IOException {
super.flush();
flushBuffer();
}
};
}
private PrintStream createOutputStream() {
return new PrintStream(outBytes, true);
}
void flushBuffer() {
// append current content
final String data = outBytes.toString();
// debugging shows that system streams are flushed rather often even
// when no new input was received, so suppress meaningless contentChanged
// events
if (!data.isEmpty()) {
// reset the byte array
outBytes.reset();
// inform listeners
contentChanged(data);
}
}
protected void contentChanged(String data) {
ConsoleEvent ce = new ConsoleEvent(data);
for (ConsoleListener listener : consoleListeners) {
listener.contentChanged(ce);
}
}
public void addConsoleListener(ConsoleListener listener) {
consoleListeners.add(listener);
}
public void removeConsoleListener(ConsoleListener listener) {
consoleListeners.remove(listener);
}
public PrintStream getOut() {
return out;
}
@Override
public void close() throws IOException {
}
}
ConsoleListener
package com.dua3.util.io;
import com.dua3.util.io.ConsoleEvent;
public interface ConsoleListener {
void contentChanged(ConsoleEvent ce);
}
ConsoleEvent
package com.dua3.util.io;
public class ConsoleEvent {
private final String data;
public ConsoleEvent(String data) {
this.data = data;
}
public String getData() {
return data;
}
}
Upvotes: 0
Reputation: 39447
System.out
is an object of type PrintStream
.
You can pass it around between classes like any other PrintStream
object.
So your ConsoleAPI.setOutput
method needs to take a PrintStream
as parameter.
Then you'll be able to do what you want.
http://docs.oracle.com/javase/7/docs/api/java/io/PrintStream.html
Upvotes: 1