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