Скрытие вызовов System.out.print класса - PullRequest
19 голосов
/ 03 декабря 2011

Я использую библиотеку Java (файл JAR).Автор файла положил в связку System.out.print и System.out.println с.Есть ли способ скрыть эти сообщения для определенного объекта?

* РЕДАКТИРОВАТЬ: похоже, что файл jar создает кучу потоков, и каждый поток имеет свои собственные System.out.println ...

Ответы [ 5 ]

41 голосов
/ 03 декабря 2011

Изменить оригинал PrintStream с Dummy , который ничего не делает с его write() методом.

Не забудьте заменить оригинал 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");
6 голосов
/ 03 декабря 2011

System.setOut(); это, вероятно, то, что вы ищете

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

Источник

4 голосов
/ 03 декабря 2011

Есть два способа сделать это, кроме того, что было опубликовано ранее:
1. Использовать декомпилятор Java, удалять каждый вызов System.out и перекомпилировать jar.Я бы рекомендовал этот , если вы выберете этот маршрут.
2. Вы можете использовать трассировку стека, чтобы найти тип вызова.(Начиная с Как найти вызывающего метода, используя трассировку стека или отражение? )

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:
(трассировки стека находятся в индексе, 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

Пример трассировки стека для записи \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 - основной класс, который я использую для проведения теста,reflection.StackTrace$1 - это мой filterStream, и я вызываю System.out.println из метода main в reflection.StackTrace.

/ e2
Это расхождение 11 или 10, по-видимому, из-за printlnзвонки print и newLine.print продолжает вызывать write, в то время как newLine напрямую записывает символ новой строки в поток.Но это не должно иметь значения, поскольку в банке не будет java.io.PrintStream.

0 голосов
/ 21 июля 2018

Решение вашего вопроса здесь .. в методе SysOutController.ignoreSysout();

0 голосов
/ 05 января 2018

Если у вас более крупная программа, рассмотрите что-то вроде

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

Это гарантирует, что вы можете включать и выключать выход в разных классах, и в то же время гарантируете, что сможете включить выход позже.

Вы, например, используете его, позвонив

toggleOutput(false) в начале каждого метода и

toggleOutput(true) в конце каждого метода.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...