web-dev-qa-db-fra.com

Rediriger System.out.println

Mon application contient de nombreuses instructions System.out.println ().

Je veux attraper les messages de println et les envoyer à l'enregistreur standard (Log4j, JUL etc.).

Comment faire ça ?

32
EK.

La classe System a un setOut et setErr qui peuvent être utilisés pour changer le flux de sortie en, par exemple, un nouveau PrintStream avec un support File ou, dans ce cas, probablement un autre flux qui utilise le sous-système de journalisation de votre choix.


Gardez à l'esprit que vous risquez de vous retrouver avec des problèmes si vous configurez votre bibliothèque de journalisation pour une sortie sur une sortie standard ou une erreur (de type récursion infinie, éventuellement).

Si c'est le cas, vous voudrez peut-être simplement remplacer vos instructions de type System.out.print Par de véritables appels de journalisation.

35
paxdiablo

J'ai eu un besoin similaire une fois. J'avais besoin d'intercepter la sortie d'un composant tiers et de réagir à un message d'erreur. Le concept ressemble à ceci:

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

La meilleure solution consiste à parcourir et à modifier toutes les instructions println pour utiliser une bibliothèque de journalisation appropriée. Ce que vous essayez de faire, c'est un gros hack.

9
Stefan Kendall

Voici comment capturer des impressions sur System.out, puis remettre les choses en ordre:

// 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
Vic Seedoubleyew

étendre PrintStream est une mauvaise solution car vous devrez remplacer toutes les méthodes print() et println(). Au lieu de cela, vous pouvez capturer le flux:

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();
    }
}

Vous pouvez maintenant le capturer comme ceci:

   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