2010-07-27 17 views
27

Sto cercando di intercettare System.out e System.err, ma mantenere la possibilità di scrivere direttamente sui flussi originali quando necessario.Java: scrittura nel vero STDOUT dopo System.setOut

PrintStream ps = System.out; 
System.setOut(new MyMagicPrintStream()); 
ps.println("foo"); 

Purtroppo, i dettagli della classe di implementazione del sistema significa che nel mio esempio, 'foo' viene inviato al MyMagicPrintStream instread del reale stdout. Qualcuno sa come ottenere riferimenti agli OutputStreams reali/originali.

Grazie!

PS: altrimenti si verificherà un errore StackOverflow < - per SEO.

risposta

29

provare questo:

PrintStream ps = new PrintStream(new FileOutputStream(FileDescriptor.out)) 
+1

(non sapevo si potesse fare!) Tuttavia, esiste un potenziale problema con questo approccio. Se qualche altra parte dell'applicazione utilizza l'oggetto System.out originale PrintStream, l'output su stdout dai due flussi potrebbe essere interlacciato casualmente. L'utilizzo di un oggetto flusso singolo sarà meno incline a questo. –

+0

Penso che non lo farà perché PrintStream non ha buffer in modo che i dati dovrebbero arrivare direttamente allo stdout, giusto? – fqsxr

+1

Sapevo che ci doveva essere un modo per ottenere il descrittore del file originale. Questo è perfetto. Grazie! – Jim

13

provare qualcosa di simile:

PrintStream original = new PrintStream(System.out); 

    // replace the System.out, here I redirect to NUL 
    System.setOut(new PrintStream(new FileOutputStream("NUL:"))); 
    System.out.println("bar"); // no output 

    // the original stream is still available 
    original.println("foo"); // output to stdout 
+0

Qual è la differenza rispetto a ciò che l'OP ha pubblicato? – cletus

+0

L'OP mantiene un riferimento che verrà modificato da setOut(). Nella mia risposta, creo un nuovo stream dalla corrente che non sarà influenzato da setOut(). Almeno, è così che lo capisco :-) – RealHowTo

+0

Wow, sono impressionato. L'ho eseguito attraverso il jvm completamente aspettandosi che fallisse come mio OP, ma funziona. Congratulazioni, è impressionante. Grazie! – Jim

2
PrintStream original = System.out; 
System.setOut(new MyMagicPrintStream()); 

// This will print to MyMagicPrintStream(); 
System.out.println("foo for MyMagicPrintStream"); 


System.setOut(original); 

// This will print to original print stream; 
System.out.println("foo for original print stream (stdout)"); 

Questo funziona per me.

+0

Non funziona per me. – dgrant

+0

non ha funzionato neanche per me; vorrei farlo – Kelly

+0

funziona per me – edwardmp

1

PrintStream original = new PrintStream(System.out); avvolge fondamentalmente il riferimento esistente - quindi se System.setOut() stava cambiando - ci dovrebbe essere alcuna differenza. Questo è probabilmente un problema con JVM particolare, ma preferirei indovinare che qualcosa non andava nel MyMagicPrintStream o nel codice che scrive sullo stdout. In realtà il seguente pezzo di codice non esattamente ciò che è previsto per il Sun 1.6.0_20-b02 per Windows:

import java.io.FileOutputStream; 
import java.io.PrintStream; 

public class SystemOutTest { 

public static void main(String args[]) { 
    try { 
     PrintStream ps = System.out; 
     System.setOut(new PrintStream(new FileOutputStream("stdout.log"))); 

     System.out.println("foo"); 
     ps.println("bar"); 
    } catch (Exception e) { 
     e.printStackTrace(); 
    } 
} 

} 

"pippo" va a stdout.log, "bar" alla console.

Inoltre, se avete bisogno di accedere all'originale standard input/out assegnato di avvio JVM - è possibile utilizzare System.console(); (basta ricordare - può essere null!)

Problemi correlati