2012-01-03 14 views
38

Ho una funzione il cui tipo di ritorno è VOID e viene stampato direttamente sulla console.reindirizzamento output della console di stringa in Java

però ho bisogno che la produzione nella stringa di modo che io possa lavorare su di esso.

Come smusso fare qualsiasi cambiamento funzione con tipo di ritorno è nulla così devo reindirizzare l'output a stringa.

Come posso reindirizzare in Java?

Ci sono molte domande riguardanti il ​​reindirizzamento stdout a stringa ma reindirizzare input solo preso da parte dell'utente e senza uscita di qualche funzione ...

risposta

75

Se la funzione è la stampa a System.out, è possibile acquisire l'uscita utilizzando la Metodo System.setOut per cambiare System.out per andare a un PrintStream fornito da voi. Se si crea un PrintStream connesso a ByteArrayOutputStream, è possibile acquisire l'output come String.

Esempio:

// Create a stream to hold the output 
    ByteArrayOutputStream baos = new ByteArrayOutputStream(); 
    PrintStream ps = new PrintStream(baos); 
    // IMPORTANT: Save the old System.out! 
    PrintStream old = System.out; 
    // Tell Java to use your special stream 
    System.setOut(ps); 
    // Print some output: goes to your special stream 
    System.out.println("Foofoofoo!"); 
    // Put things back 
    System.out.flush(); 
    System.setOut(old); 
    // Show what happened 
    System.out.println("Here: " + baos.toString()); 

stampe Questo programma una sola riga:

Here: Foofoofoo! 
+4

Non dimenticare, quando si è fatto, per chiamare System.out.flush(), e quindi passare System.out tornare al normale (o, più correttamente, il precedente) System.out. Vedo che @Ernest ha aggiunto questo nel suo codice. – user949300

+3

Inoltre, non dimenticare che questo crea problemi di threading, non solo per questo metodo (che potresti risolvere sincronizzandolo) ma per qualsiasi altro codice che stampa su stdout. 'Baos.toString()' 'potrebbe facilmente essere "worldofoo Foofohello!"' – yshavit

+0

@Ernest: got it thanks ... – SRK

15

Ecco una classe di utilità di nome ConsoleOutputCapturer. Consente all'output di passare alla console esistente, ma dietro la scena continua a catturare il testo di output. Puoi controllare cosa catturare con i metodi start/stop. In altre parole, chiama start per avviare l'acquisizione dell'output della console e, una volta terminato l'acquisizione, puoi chiamare il metodo stop che restituisce un valore String che trattiene l'output della console per la finestra temporale tra le chiamate start-stop. Questa classe non è thread-safe però.

import java.io.ByteArrayOutputStream; 
import java.io.IOException; 
import java.io.OutputStream; 
import java.io.PrintStream; 
import java.util.Arrays; 
import java.util.List; 

public class ConsoleOutputCapturer { 
    private ByteArrayOutputStream baos; 
    private PrintStream previous; 
    private boolean capturing; 

    public void start() { 
     if (capturing) { 
      return; 
     } 

     capturing = true; 
     previous = System.out;  
     baos = new ByteArrayOutputStream(); 

     OutputStream outputStreamCombiner = 
       new OutputStreamCombiner(Arrays.asList(previous, baos)); 
     PrintStream custom = new PrintStream(outputStreamCombiner); 

     System.setOut(custom); 
    } 

    public String stop() { 
     if (!capturing) { 
      return ""; 
     } 

     System.setOut(previous); 

     String capturedValue = baos.toString();    

     baos = null; 
     previous = null; 
     capturing = false; 

     return capturedValue; 
    } 

    private static class OutputStreamCombiner extends OutputStream { 
     private List<OutputStream> outputStreams; 

     public OutputStreamCombiner(List<OutputStream> outputStreams) { 
      this.outputStreams = outputStreams; 
     } 

     public void write(int b) throws IOException { 
      for (OutputStream os : outputStreams) { 
       os.write(b); 
      } 
     } 

     public void flush() throws IOException { 
      for (OutputStream os : outputStreams) { 
       os.flush(); 
      } 
     } 

     public void close() throws IOException { 
      for (OutputStream os : outputStreams) { 
       os.close(); 
      } 
     } 
    } 
} 
+0

Funziona alla grande, bel lavoro! –

+1

Soluzione davvero bella, sebbene suggerirei una piccola aggiunta, chiamate il metodo close() su baos stream nel metodo stop() appena prima di impostarlo su null per rilasciare tutte le risorse. – davidgale

+0

Lavoro perfetto! :) – Developer66

Problemi correlati