20

I'm using a java library (jar file). The author of the file put in a bunch of System.out.print and System.out.printlns. Is there any way to hide these messages for a particular object?

*EDIT: It looks like the jar file seems to be creating a bunch of threads and each thread has it's own System.out.println's...

K2xL
  • 9,730
  • 18
  • 64
  • 101

5 Answers5

43

Change original PrintStream with a Dummy one which does nothing on it's write() method.

Don't forget to replace original PrintStream when you finished.

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");
Kerem Baydoğan
  • 10,475
  • 1
  • 43
  • 50
  • 2
    thanks for the quick answer, but won't this hide all system.outs? i want to keep the ones that i have in my program but hide the ones that the jar created. – K2xL Dec 02 '11 at 22:46
  • 1
    Just before a method from jar invoked use `System.setOut(dummyStream);`. Just after a method from jar invoked use `System.setOut(originalStream);`. Ok? – Kerem Baydoğan Dec 02 '11 at 22:50
  • 1
    Not exactly. The jar file creates a bunch of threads that each do a System.out... – K2xL Dec 03 '11 at 03:52
  • 5
    @K2xL in that case use **`dummyStream`** all the time. When you need to print something to console use **`originalStream`**. – Kerem Baydoğan Dec 04 '11 at 22:02
7

System.setOut(); is probably what you're looking for

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

Source

Grambot
  • 4,370
  • 5
  • 28
  • 43
  • Note: This will stop the `System.out.println` and `System.out.print` calls from *all* classes. – Jeffrey Dec 02 '11 at 22:38
  • ah yes i just asked the author of the above answer this question... so there's no way to hide it from just one specific file? i have some system.outs in my class that i don't want to hide... just the ones the author of this jar has.. – K2xL Dec 02 '11 at 22:46
  • @K2xL what do you mean by **just one specific file**? Please show us the problematic part of your code. – Kerem Baydoğan Dec 03 '11 at 00:03
  • For hiding from one specific class file or multiple class files you could aspect. Aspectj with above would work great! – Vishal Biyani Dec 03 '11 at 00:08
4

There are two ways I can think of doing this other than what has been previously posted:
1. Use a Java decompiler and remove each System.out call and recompile the jar. I would reccommend this one if you choose this route.
2. You can use the stack trace to find the calling type. (From 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);

Where classNames is the fully qualified name of every class in the jar file and someNumber is the correct place in the stack you need to be looking at (probably 1 or 2).

/e1
After some testing I believe the number you will need for someNumber is either 10 or 11. This is because System.out.print does not directly call the write method.

Example stack trace for writing h:
(Stack traces are in index, getClassName, getFileName, getMethodName order).

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

Example stack trace for writing \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    newLine
9   java.io.PrintStream null    println
10  reflection.StackTrace   StackTrace.java main

reflection.StackTrace is the main class I'm using to do the test. reflection.StackTrace$1 is my filterStream and I'm calling System.out.println from the main method in reflection.StackTrace.

/e2
This 11 or 10 discrepancy appears to be because println calls print and newLine. print goes on to call write while newLine directly writes the new line character to the stream. But this shouldn't matter since the jar will not contain java.io.PrintStream.

Community
  • 1
  • 1
Jeffrey
  • 44,417
  • 8
  • 90
  • 141
  • interesting solution... it seems overly complicated but i guess it might be the only solution... – K2xL Dec 03 '11 at 03:54
1

Solution of your question is here.. in method SysOutController.ignoreSysout();

0

If you have a bigger programm consider something like

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);
    }
}

This gurantees that you can toggle output on and off in different classes, while beeing guranteed to be able to turn the output on later.

You for example use it by calling

toggleOutput(false) at the start of each method and

toggleOutput(true) at the end of each method.

HopefullyHelpful
  • 1,652
  • 3
  • 21
  • 37