我有一個Java程序,輸出一些文本到控制檯。它使用print
,println
和其他一些方法來做到這一點。我怎麼能讀Java控制檯輸出到字符串緩衝區
在程序結束時,我想讀取控制檯中的所有文本並將其複製到字符串緩衝區中。我怎麼能在Java中做到這一點?我需要分別閱讀stdout
和stderr
。
我有一個Java程序,輸出一些文本到控制檯。它使用print
,println
和其他一些方法來做到這一點。我怎麼能讀Java控制檯輸出到字符串緩衝區
在程序結束時,我想讀取控制檯中的所有文本並將其複製到字符串緩衝區中。我怎麼能在Java中做到這一點?我需要分別閱讀stdout
和stderr
。
好吧,這是一個有趣的問題。 Dosen似乎是一次解決所有PrintStream
方法的優雅方式。 (不幸的是沒有FilterPrintStream
)
我雖然寫了一個醜陋的基於反射的解決方法(而不是在生產代碼中使用我想:)
class LoggedPrintStream extends PrintStream {
final StringBuilder buf;
final PrintStream underlying;
LoggedPrintStream(StringBuilder sb, OutputStream os, PrintStream ul) {
super(os);
this.buf = sb;
this.underlying = ul;
}
public static LoggedPrintStream create(PrintStream toLog) {
try {
final StringBuilder sb = new StringBuilder();
Field f = FilterOutputStream.class.getDeclaredField("out");
f.setAccessible(true);
OutputStream psout = (OutputStream) f.get(toLog);
return new LoggedPrintStream(sb, new FilterOutputStream(psout) {
public void write(int b) throws IOException {
super.write(b);
sb.append((char) b);
}
}, toLog);
} catch (NoSuchFieldException shouldNotHappen) {
} catch (IllegalArgumentException shouldNotHappen) {
} catch (IllegalAccessException shouldNotHappen) {
}
return null;
}
}
...可以像使用這樣的:
public class Test {
public static void main(String[] args) {
// Create logged PrintStreams
LoggedPrintStream lpsOut = LoggedPrintStream.create(System.out);
LoggedPrintStream lpsErr = LoggedPrintStream.create(System.err);
// Set them to stdout/stderr
System.setOut(lpsOut);
System.setErr(lpsErr);
// Print some stuff
System.out.print("hello ");
System.out.println(5);
System.out.flush();
System.err.println("Some error");
System.err.flush();
// Restore System.out/System.err
System.setOut(lpsOut.underlying);
System.setErr(lpsErr.underlying);
// Print the logged output
System.out.println("----- Log for System.out: -----\n" + lpsOut.buf);
System.out.println("----- Log for System.err: -----\n" + lpsErr.buf);
}
}
結果輸出:
hello 5
Some error
----- Log for System.out: -----
hello 5
----- Log for System.err: -----
Some error
(注壽呃,FilterOutputStream
中的out
字段是受保護和記錄的,因此它是API的一部分:-)
一旦程序運行完畢,您就無法做到這一點。您需要在程序開始寫入輸出之前執行此操作。有關如何替換stdout和stderr的詳細信息,請參閱this article。核心電話是System.setOut()
和System.setErr()
。
不要做之後,在第一個System.out.print()
被調用之前創建兩個StringBuilder
對象,並將您想要保存的每個字符串追加到相應的StringBuilder
。
您可以使用PipedInputStream和PipedOutputStream。
//create pairs of Piped input and output streasm for std out and std err
final PipedInputStream outPipedInputStream = new PipedInputStream();
final PrintStream outPrintStream = new PrintStream(new PipedOutputStream(
outPipedInputStream));
final BufferedReader outReader = new BufferedReader(
new InputStreamReader(outPipedInputStream));
final PipedInputStream errPipedInputStream = new PipedInputStream();
final PrintStream errPrintStream = new PrintStream(new PipedOutputStream(
errPipedInputStream));
final BufferedReader errReader = new BufferedReader(
new InputStreamReader(errPipedInputStream));
final PrintStream originalOutStream = System.out;
final PrintStream originalErrStream = System.err;
final Thread writingThread = new Thread(new Runnable() {
@Override
public void run() {
try {
System.setOut(outPrintStream);
System.setErr(errPrintStream);
// You could also set the System.in here using a
// PipedInputStream
DoSomething();
// Even better would be to refactor DoSomething to accept
// PrintStream objects as parameters to replace all uses of
// System.out and System.err. DoSomething could also have
// an overload with DoSomething() calling:
DoSomething(outPrintStream, errPrintStream);
} finally {
// may also want to add a catch for exceptions but it is
// essential to restore the original System output and error
// streams since it can be very confusing to not be able to
// find System.out output on your console
System.setOut(originalOutStream);
System.setErr(originalErrStream);
//You must close the streams which will auto flush them
outPrintStream.close();
errPrintStream.close();
}
} // end run()
}); // end writing thread
//Start the code that will write into streams
writingThread.start();
String line;
final List<String> completeOutputStreamContent = new ArrayList<String>();
while ((line = outReader.readLine()) != null) {
completeOutputStreamContent.add(line);
} // end reading output stream
final List<String> completeErrorStreamContent = new ArrayList<String>();
while ((line = errReader.readLine()) != null) {
completeErrorStreamContent.add(line);
} // end reading output stream
這兩行代碼會將您的輸出置於文本文件中,或者您可以根據需要更改目的地。
//創建一個文件: System.setOut(新的PrintStream(新FileOutputStream中( 「d:/MyOutputFile.txt」))); //將輸出重定向到文件: System.out.println(「Hello to custom output stream!」);
希望其幫助你.. :)
這是一個實用工具類名爲ConsoleOutputCapturer。它允許輸出到現有控制檯,但在場景後面繼續捕獲輸出文本。您可以控制使用啓動/停止方法捕獲的內容。換句話說,調用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();
}
}
}
}
哇!非常感謝。這個對我有用。 – Jacob 2010-12-03 05:49:28