2012-01-03 40 views
38

Tôi có một hàm có loại trả về là VOID và nó in trực tiếp trên bảng điều khiển.Đầu ra của bảng điều khiển chuyển hướng thành chuỗi trong java

Tuy nhiên, tôi cần đầu ra đó trong chuỗi để tôi có thể làm việc trên đó.

Vì tôi không thể thực hiện bất kỳ thay đổi nào với chức năng với kiểu trả về là VOID nên tôi phải chuyển hướng đầu ra đó tới chuỗi.

Làm cách nào để chuyển hướng nó trong JAVA?

Có rất nhiều câu hỏi liên quan đến chuyển hướng stdout để chuỗi nhưng họ chuyển hướng chỉ đầu vào lấy từ người dùng và không sản lượng của một số chức năng ...

Trả lời

75

Nếu hàm được in để System.out, bạn có thể chụp ra rằng bằng cách sử dụng System.setOut để thay đổi System.out để truy cập vào số PrintStream do bạn cung cấp. Nếu bạn tạo một PrintStream được kết nối với một số ByteArrayOutputStream, thì bạn có thể chụp đầu ra dưới dạng String.

Ví dụ:

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

Chương trình này in ra chỉ một dòng:

Here: Foofoofoo! 
+4

Đừng quên, khi bạn đã hoàn tất, hãy gọi System.out.flush(), sau đó chuyển System.out trở lại bình thường (hoặc, đúng hơn, trước đó) System.out. Tôi thấy rằng @Ernest đã thêm vào mã của anh ấy. – user949300

+3

Ngoài ra, đừng quên rằng điều này tạo ra các vấn đề luồng, không chỉ cho phương pháp này (mà bạn có thể giải quyết bằng cách đồng bộ hóa nó) nhưng đối với bất kỳ mã nào khác in ra stdout. 'baos.toString()' có thể dễ dàng là "" Foofohello worldofoo! "' – yshavit

+0

@Ernest: đã nhờ nó ... – SRK

15

Đây là một lớp tiện ích mang tên ConsoleOutputCapturer. Nó cho phép đầu ra để đi đến giao diện điều khiển hiện có tuy nhiên đằng sau cảnh giữ bắt văn bản đầu ra. Bạn có thể kiểm soát những gì để nắm bắt với các phương pháp bắt đầu/dừng. Nói cách khác, bắt đầu gọi bắt đầu bắt đầu giao diện điều khiển và khi bạn hoàn thành việc chụp, bạn có thể gọi phương thức dừng trả về giá trị String giữ đầu ra giao diện điều khiển cho cửa sổ thời gian giữa các cuộc gọi dừng. Lớp này không phải là thread-safe.

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

Hoạt động tuyệt vời, công việc tốt đẹp! –

+1

Giải pháp thực sự tốt đẹp, mặc dù tôi sẽ đề nghị thêm một chút, gọi phương thức close() trên luồng baos trong phương thức stop() ngay trước khi thiết lập nó thành null để giải phóng tất cả các tài nguyên. – davidgale

+0

Công việc hoàn hảo! :) – Developer66

Các vấn đề liên quan