Hiding System.out.print calls of a class

前端 未结 5 1404
别那么骄傲
别那么骄傲 2021-02-02 13:16

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

相关标签:
5条回答
  • 2021-02-02 13:21

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

    0 讨论(0)
  • 2021-02-02 13:26

    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");
    
    0 讨论(0)
  • 2021-02-02 13:33

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

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

    Source

    0 讨论(0)
  • 2021-02-02 13:46

    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.

    0 讨论(0)
  • 2021-02-02 13:46

    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.

    0 讨论(0)
提交回复
热议问题