2011-12-02 57 views
15

我正在使用java庫(jar文件)。該文件的作者放在一堆System.out.printSystem.out.println s。有什麼方法可以隱藏特定對象的這些消息嗎?隱藏System.out.print類的調用

*編輯:它看起來像jar文件似乎建立了一堆的線程和每個線程都有它自己的System.out.println的...

回答

6

System.setOut();可能是你在找什麼

System.setOut(new PrintStream(new OutputStream() { 
    public void write(int b) { 
    // NO-OP 
    } 
})); 

Source

+0

注意:這將停止* all *類的'System.out.println'和'System.out.print'調用。 – Jeffrey

+0

啊是的,我只是問上述答案的作者這個問題......所以沒有辦法隱藏它只有一個特定的文件?我在我的課堂上有一些system.out,我不想隱藏...只是這個罐子的作者.. – K2xL

+0

@ K2xL看到我的回答 – Jeffrey

35

更改原始的PrintStream虛擬上根本上是什麼方法。

當你完成時,不要忘記取代原來的PrintStream

System.out.println("NOW YOU CAN SEE ME"); 

PrintStream originalStream = System.out; 

PrintStream dummyStream = new PrintStream(new OutputStream(){ 
    public void write(int b) { 
     // NO-OP 
    } 
}); 

System.setOut(dummyStream); 
System.out.println("NOW YOU CAN NOT"); 

System.setOut(originalStream); 
System.out.println("NOW YOU CAN SEE ME AGAIN"); 
+1

感謝您的快速回答,但不會隱藏所有system.outs?我想保留我在程序中的那些,但隱藏了那個jar創建的那些。 – K2xL

+0

就在從調用jar的方法之前使用'System.setOut(dummyStream);'。在從jar中調用方法之後使用'System.setOut(originalStream);'。好? –

+1

不完全。 jar文件創建了一組線程,每個線程都執行System.out ... – K2xL

3

有兩種方法我能想到做的比之前已經張貼了這個其他的:
1.使用Java反編譯器,並刪除每個System.out調用並重新編譯罐子。如果您選擇此路線,我會推薦this one
2.您可以使用堆棧跟蹤來查找調用類型。 (從How do I find the caller of a method using stacktrace or reflection?

List<String> classNames = ... 
final PrintStream originalOut = System.out; 
PrintStream filterStream = new PrintStream(new OutputStream() { 
    public void write(int b) { 
     StackTraceElement[] stackTraceElements = Thread.currentThread().getStackTrace(); 
     if(!classNames.contains(stackTraceElements[someNumber].getClassName()){ 
       originalOut.write(b); 
     } 
    } 
}); 
System.setOut(filterStream); 

哪裏classNames是每一個類的完全限定名的jar文件和someNumber是在堆棧中的正確的地方,你需要看的(大概1或2)。

/E1
一些測試,我相信你將需要someNumber數爲10或11,這是因爲System.out.print不直接調用write方法後。用於寫入h

例堆棧跟蹤:
(堆棧痕跡是索引,getClassNamegetFileNamegetMethodName順序)。寫\n

0 java.lang.Thread null getStackTrace 
1 reflection.StackTrace$1 StackTrace.java write 
2 java.io.OutputStream null write 
3 java.io.PrintStream null write 
4 sun.nio.cs.StreamEncoder null writeBytes 
5 sun.nio.cs.StreamEncoder null implFlushBuffer 
6 sun.nio.cs.StreamEncoder null flushBuffer 
7 java.io.OutputStreamWriter null flushBuffer 
8 java.io.PrintStream null write 
9 java.io.PrintStream null print 
10 java.io.PrintStream null println 
11 reflection.StackTrace StackTrace.java main 

實例堆棧跟蹤:

0 java.lang.Thread null getStackTrace 
1 reflection.StackTrace$1 StackTrace.java write 
2 java.io.OutputStream null write 
3 java.io.PrintStream null write 
4 sun.nio.cs.StreamEncoder null writeBytes 
5 sun.nio.cs.StreamEncoder null implFlushBuffer 
6 sun.nio.cs.StreamEncoder null flushBuffer 
7 java.io.OutputStreamWriter null flushBuffer 
8 java.io.PrintStream null newLine 
9 java.io.PrintStream null println 
10 reflection.StackTrace StackTrace.java main 

reflection.StackTrace是我用來做測試的主類。 reflection.StackTrace$1是我的filterStream,我打電話給reflection.StackTracemain方法System.out.println

/E2
這11或10的差異似乎是因爲println呼叫printnewLineprint繼續呼叫write,而newLine直接將新行字符寫入流中。但這不應該因爲該罐子不包含java.io.PrintStream

+0

有趣的解決方案...它似乎過於複雜,但我想這可能是唯一的解決方案... – K2xL

0

如果你有一個更大的PROGRAMM考慮像

public abstract class Output { 
    private static final PrintStream out = System.out; 
    private static final PrintStream dummy = new PrintStream(new OutputStream() {@Override public void write(int b){} }); 

    private static boolean globalOutputOn = true; 
    public static void toggleOutput() { 
     System.setOut((globalOutputOn=!globalOutputOn)?dummy:out); 
    } 

    public static void toggleOutput(boolean on) { 
     globalOutputOn = on; 
     System.setOut(on?out:dummy); 
    } 
} 

此註冊就可以在不同的班級和關閉切換輸出,同時beeing存在保證能夠打開輸出上更高版本。

您例如通過調用

toggleOutput(false)在每個方法的開始和

toggleOutput(true)在每個方法的末尾使用它。