Скрытие вызовов System.out.print класса
Я использую java-библиотеку (файл jar). Автор файла помещен в кучу System.out.print
и System.out.println
s. Есть ли способ скрыть эти сообщения для определенного объекта?
* EDIT: похоже, что файл jar создает цепочку потоков, и каждый поток имеет свой собственный System.out.println's...
Ответы
Ответ 1
Измените оригинальный 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");
Ответ 2
System.setOut();
, вероятно, то, что вы ищете
System.setOut(new PrintStream(new OutputStream() {
public void write(int b) {
// NO-OP
}
}));
Источник
Ответ 3
Есть два способа, я могу думать о том, чтобы делать это иначе, чем то, что было ранее опубликовано:
1. Используйте декомпилятор Java и удалите каждый вызов System.out
и перекомпилируйте банку. Я бы рекомендовал этот, если вы выберете этот маршрут.
2. Вы можете использовать трассировку стека для поиска вызывающего типа. (Из Как найти вызывающего метода с использованием stacktrace или 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
:
(Трассировки стека находятся в индексе, getClassName
, getFileName
, getMethodName
порядок).
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
.
/е2
Это 11 или 10 несоответствий, по-видимому, связано с тем, что println
вызывает print
и newLine
. print
переходит к вызову write
, а newLine
непосредственно пишет новый символ строки в поток. Но это не имеет значения, поскольку в jar не будет java.io.PrintStream
.
Ответ 4
Если у вас есть более крупная программа, рассмотрите что-то вроде
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);
}
}
Это гарантирует, что вы можете включать и отключать вывод в разных классах, в то время как beur guranteed, чтобы иметь возможность позже выводить результат.
Вы, например, используете его, вызывая
toggleOutput(false)
в начале каждого метода и
toggleOutput(true)
в конце каждого метода.