2010-07-27 17 views
27

Tôi đang cố gắng chặn System.out và System.err, nhưng vẫn duy trì khả năng ghi trực tiếp vào luồng gốc khi cần.Java: Ghi vào STDOUT thực sau System.setOut

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

Thật không may, chi tiết về việc triển khai của lớp Hệ thống có nghĩa là trong ví dụ của tôi, "foo" được gửi tới bản in của MyMagicPrintStream của phần cứng thực. Có ai biết làm thế nào để có được tham chiếu đến OutputStreams thực/ban đầu.

Cảm ơn!

PS: Điều này sẽ dẫn đến kết quả là StackOverflowError < - dành cho SEO.

Trả lời

29

thử điều này:

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

(Tôi không biết bạn có thể làm điều đó!) Tuy nhiên, có một vấn đề tiềm năng với cách tiếp cận này. Nếu một phần khác của ứng dụng của bạn đang sử dụng đối tượng System.out 'PrintStream' ban đầu, thì đầu ra thành stdout từ hai luồng có thể được xen kẽ ngẫu nhiên. Việc sử dụng một đối tượng luồng đơn sẽ ít bị ảnh hưởng hơn. –

+0

Tôi nghĩ rằng nó sẽ không phải vì PrintStream không có bộ đệm nên dữ liệu nên trực tiếp đến stdout, phải không? – fqsxr

+1

Tôi biết phải có một cách để có được bộ mô tả tập tin gốc. Đây là hoàn hảo. Cảm ơn! – Jim

13

Hãy thử một cái gì đó như thế này:

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

Điều này khác với những gì OP được đăng? – cletus

+0

OP giữ một tham chiếu ra ngoài sẽ được thay đổi bởi setOut(). Trong câu trả lời của tôi, tôi tạo một Stream mới từ hiện tại mà sẽ không bị ảnh hưởng bởi setOut(). Ít nhất, đó là cách tôi hiểu nó :-) – RealHowTo

+0

Wow, tôi rất ấn tượng. Tôi chạy nó thông qua các JVM đầy đủ mong đợi nó thất bại như OP của tôi, nhưng nó hoạt động. Xin chúc mừng, điều đó thật ấn tượng. Cảm ơn! – 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)"); 

này làm việc cho tôi.

+0

Không hiệu quả với tôi. – dgrant

+0

cũng không làm việc cho tôi; ước gì. – Kelly

+0

không hoạt động với tôi – edwardmp

1

PrintStream original = new PrintStream(System.out); về cơ bản bao bọc tham chiếu hiện tại - vì vậy nếu System.setOut() đang thay đổi nó - sẽ không có sự khác biệt. Đó có lẽ là một vấn đề với JVM cụ thể, nhưng tôi thà đoán rằng có điều gì đó sai với MyMagicPrintStream, hoặc mã viết cho stdout. Trên thực tế các đoạn mã sau đây không chính xác những gì được mong đợi trên Sun 1.6.0_20-b02 cho 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(); 
    } 
} 

} 

"foo" đi vào stdout.log, "bar" vào giao diện điều khiển.

Ngoài ra, nếu bạn cần truy cập vào gốc stdin/ra giao của JVM khởi động - bạn có thể sử dụng System.console(); (chỉ cần nhớ - nó có thể được null!)

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