web-dev-qa-db-ja.com

リダイレクトSystem.out.println

私のアプリケーションには多くのSystem.out.println()ステートメントがあります。

Printlnからのメッセージをキャッチして、標準のロガー(Log4j、JULなど)に送信したいのですが。

どうやってするか ?

32
EK.

Systemクラスには setOutsetErr があり、これらを使用して、出力ストリームを、たとえば、バッキングPrintStreamを持つ新しいFileに変更したり、この場合、おそらく選択したロギングサブシステムを使用する別のストリーム。


ログ出力ライブラリを標準出力または(おそらく無限再帰型の)エラーに出力するように構成した場合、問題が発生する可能性があることに注意してください。

その場合は、System.out.printタイプのステートメントを実際のロギング呼び出しに置き換えてください。

35
paxdiablo

かつて同様のニーズがありました。一部のサードパーティコンポーネントの出力をインターセプトし、エラーメッセージに対応する必要がありました。概念は次のようになります。

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
}
30
Wizard of Kneup

より良い解決策は、適切なロギングライブラリを使用するようにすべてのprintlnステートメントを実行して変更することです。あなたがやろうとしているのは大きなハックです。

9
Stefan Kendall

これは、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();
3

すべての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);
2
sergeych