私のアプリケーションには多くのSystem.out.println()ステートメントがあります。
Printlnからのメッセージをキャッチして、標準のロガー(Log4j、JULなど)に送信したいのですが。
どうやってするか ?
かつて同様のニーズがありました。一部のサードパーティコンポーネントの出力をインターセプトし、エラーメッセージに対応する必要がありました。概念は次のようになります。
private class Interceptor extends PrintStream
{
public Interceptor(OutputStream out)
{
super(out, true);
}
@Override
public void print(String s)
{//do what ever you like
super.print(s);
}
}
public static void main(String[] args)
{
PrintStream origOut = System.out;
PrintStream interceptor = new Interceptor(origOut);
System.setOut(interceptor);// just add the interceptor
}
より良い解決策は、適切なロギングライブラリを使用するようにすべてのprintlnステートメントを実行して変更することです。あなたがやろうとしているのは大きなハックです。
これは、System.outにプリントをキャプチャして、順番に戻す方法です。
// Start capturing
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
System.setOut(new PrintStream(buffer));
// Run what is supposed to output something
...
// Stop capturing
System.setOut(new PrintStream(new FileOutputStream(FileDescriptor.out)));
// Use captured content
String content = buffer.toString();
buffer.reset();
すべてのprint()
およびprintln()
メソッドをオーバーライドする必要があるため、PrintStreamの拡張は不適切なソリューションです。代わりに、ストリームをキャプチャできます。
public class ConsoleInterceptor {
public interface Block {
void call() throws Exception;
}
public static String copyOut(Block block) throws Exception {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
PrintStream printStream = new PrintStream(bos, true);
PrintStream oldStream = System.out;
System.setOut(printStream);
try {
block.call();
}
finally {
System.setOut(oldStream);
}
return bos.toString();
}
}
これで、次のようにキャプチャできます。
String result = ConsoleInterceptor.copyOut(() ->{
System.out.print("hello world");
System.out.print('!');
System.out.println();
System.out.println("foobar");
});
assertEquals("hello world!\nfoobar\n", result);