2012-01-03 11 views
38

Tengo una función cuyo tipo de devolución es VACÍO y se imprime directamente en la consola.Redirige la salida de la consola a la cadena en java

Sin embargo, necesito esa salida en cadena para que pueda trabajar en ella.

Como no puedo hacer ningún cambio con la función con el tipo de retorno es VACÍO, así que tengo que redirigir esa salida a la cadena.

¿Cómo puedo redirigirlo en JAVA?

Hay muchas preguntas con respecto a la reorientación de la salida estándar de cadena, pero que vuelven a dirigir solamente la entrada tomada de usuario y no la salida de alguna función ...

Respuesta

75

Si la función está imprimiendo a System.out, puede capturar esa salida mediante el uso de la System.setOut método para cambiar System.out para ir a un PrintStream proporcionado por usted. Si crea un PrintStream conectado a un ByteArrayOutputStream, puede capturar el resultado como String.

Ejemplo:

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

impresiones de este programa una sola línea:

Here: Foofoofoo! 
+4

No se olvide, cuando haya terminado, para llamar System.out.flush(), y luego cambiar System.out de nuevo a la normal (o, más correctamente, la anterior) System.out. Veo que @Ernest ha agregado eso en su código. – user949300

+3

Además, no olvide que esto crea problemas de enhebrado, no solo para este método (que puede resolver sincronizándolo) sino también para cualquier otro código que imprima en stdout. 'baos.toString()' podría ser fácilmente '' Foofohello worldofoo! ' – yshavit

+0

@Ernest: tengo que agradecer ... – SRK

15

Aquí es una clase de utilidad denominado ConsoleOutputCapturer. Permite que la salida vaya a la consola existente, pero detrás de la escena sigue capturando el texto de salida. Puede controlar qué capturar con los métodos de inicio/detención. En otras palabras, llame a start para comenzar a capturar la salida de la consola y una vez que termine de capturar puede llamar al método stop que devuelve un valor String que contiene la salida de la consola para la ventana de tiempo entre las llamadas start-stop. Sin embargo, esta clase no es segura para subprocesos.

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

¡Funciona genial, buen trabajo! –

+1

Una solución realmente agradable, aunque sugeriría una pequeña adición, llame al método close() en la secuencia baos en el método stop() justo antes de establecerlo en nulo para liberar todos los recursos. – davidgale

+0

¡Perfecto trabajo! :) – Developer66

Cuestiones relacionadas