2012-01-03 132 views
38

我有一个功能,它的返回类型是VOID,它直接在控制台上打印。将控制台输出重定向到java中的字符串

但是我需要在字符串中的输出,以便我可以在它上面工作。

由于我不能使用返回类型为VOID的函数进行任何更改,所以我必须将该输出重定向到字符串。

如何在JAVA中重定向它?

有关于标准输出重定向到串了很多问题,但他们只重定向根据用户拍摄的输入,而不是某些功能的输出...

回答

75

如果该函数打印到System.out,您可以通过使用捕捉输出System.setOut方法将System.out更改为您提供的PrintStream。如果创建连接到ByteArrayOutputStreamPrintStream,则可以将输出捕获为String

实施例:

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

这个程序打印只有一行:

Here: Foofoofoo! 
+4

不要忘了,完成后调用System.out.flush(),然后将System.out切换回正常(或更正确的说,前面的)System.out。我看到@Ernest已将其添加到他的代码中。 – user949300 2012-01-03 05:42:29

+3

另外,不要忘记,这会创建线程问题,不仅仅是针对此方法(您可以通过同步它来解决),而是针对打印到标准输出的任何其他代码。 'baos.toString()'很容易就可以''Foofohello worldofoo!'' – yshavit 2012-01-03 06:01:01

+0

@Ernest:得到它谢谢... – SRK 2012-01-05 10:35:54

15

下面是名为ConsoleOutputCapturer一个工具类。它允许输出到现有控制台,但在场景后面继续捕获输出文本。您可以控制使用启动/停止方法捕获的内容。换句话说,调用start开始捕获控制台输出,一旦完成捕获,您可以调用stop方法,该方法返回一个String值,该值持有控制台输出,用于启动和停止调用之间的时间窗口。这个类虽然不是线程安全的。

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

工作很好,工作很好! – 2016-06-09 12:09:17

+1

真的很好的解决方案,虽然我会建议一点点补充,但是在将它设置为null之前,在stop()方法的baos流上调用close()方法以释放所有资源。 – davidgale 2016-07-20 09:43:56

+0

完美的作品! :) – Developer66 2018-01-06 11:26:50

相关问题