Einleitung

In Java-Anwendungen kann es nötig sein, die Konsolenausgabe (System.out) oder die Fehlerausgabe (System.err) mitzuschneiden. Die Gründe dafür sind vielfältig:

  • Unit-Tests: Manche Tests prüfen, ob bestimmte Texte in der Standardausgabe erscheinen.
  • Debugging und Logging: Falls eine genutzte Bibliothek kein Logging-Framework unterstützt und nur System.out oder System.err verwendet, kann man die Ausgabe umleiten.
  • Speicherung und Analyse: Um die Konsolenausgabe später weiterzuverarbeiten oder zu protokollieren.

Vorgehen

In Java kann die Standardausgabe und Standardfehlerausgabe durch Umleiten der Streams System.out und System.err auf eigene Streams mitgeschnitten werden.

1. Nutzung von ByteArrayOutputStream

Ein einfacher Ansatz ist, die Standardstreams auf einen ByteArrayOutputStream umzuleiten:

import java.io.ByteArrayOutputStream;
import java.io.PrintStream;

public class StreamRedirectExample {
    public static void main(String[] args) {
        // Original-Streams speichern
        PrintStream originalOut = System.out;
        PrintStream originalErr = System.err;
        
        // Neue Streams erzeugen
        ByteArrayOutputStream outContent = new ByteArrayOutputStream();
        ByteArrayOutputStream errContent = new ByteArrayOutputStream();
        
        System.setOut(new PrintStream(outContent));
        System.setErr(new PrintStream(errContent));
        
        // Test-Ausgaben
        System.out.println("Dies ist eine normale Ausgabe.");
        System.err.println("Dies ist eine Fehlerausgabe.");
        
        // Zurücksetzen der Streams
        System.setOut(originalOut);
        System.setErr(originalErr);
        
        // Ergebnisse anzeigen
        System.out.println("Mitgeschnittene Ausgabe: " + outContent.toString());
        System.out.println("Mitgeschnittene Fehlerausgabe: " + errContent.toString());
    }
}
Code-Sprache: JavaScript (javascript)
2. Nutzung eines eigenen Output-Streams

Ein anderer Ansatz ist, einen eigenen OutputStream zu erstellen, der die Daten an mehrere Ziele weiterleitet:

import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintStream;

public class TeeOutputStream extends OutputStream {
    private final OutputStream out1;
    private final OutputStream out2;

    public TeeOutputStream(OutputStream out1, OutputStream out2) {
        this.out1 = out1;
        this.out2 = out2;
    }

    @Override
    public void write(int b) throws IOException {
        out1.write(b);
        out2.write(b);
    }

    @Override
    public void flush() throws IOException {
        out1.flush();
        out2.flush();
    }

    @Override
    public void close() throws IOException {
        out1.close();
        out2.close();
    }

    public static void main(String[] args) {
        PrintStream originalOut = System.out;
        ByteArrayOutputStream outContent = new ByteArrayOutputStream();
        PrintStream teeStream = new PrintStream(new TeeOutputStream(originalOut, outContent));
        
        System.setOut(teeStream);
        System.out.println("Diese Ausgabe wird sowohl in die Konsole als auch in den Stream geschrieben.");
        
        System.setOut(originalOut);
        System.out.println("Mitgeschnittene Ausgabe: " + outContent.toString());
    }
}
Code-Sprache: JavaScript (javascript)
3. Nutzung eines Logging-Frameworks

Falls Logging gewünscht ist, kann System.out mit einem Logging-Framework wie SLF4J oder Logback umgeleitet werden:

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.PrintStream;

public class LogRedirectExample {
    private static final Logger logger = LoggerFactory.getLogger(LogRedirectExample.class);
    
    public static void main(String[] args) {
        System.setOut(new PrintStream(System.out) {
            @Override
            public void println(String x) {
                logger.info(x);
            }
        });
        
        System.out.println("Diese Nachricht wird geloggt.");
    }
}
Code-Sprache: JavaScript (javascript)

Fazit

Das Mitschneiden von System.out und System.err ist in Java einfach möglich. Je nach Bedarf kann man einen einfachen ByteArrayOutputStream nutzen, eine eigene OutputStream-Implementierung schreiben oder die Ausgabe direkt an ein Logging-Framework weiterleiten. Welcher Ansatz gewählt wird, hängt vom jeweiligen Anwendungsfall ab.