2017-01-25 2 views
1

Не существует способа (независимо от того, как «хакерство»), чтобы обнаружить, когда Java System.err был записан в , чтобы иметь возможность выполнять логику, если и когда это произойдет? — Я сейчас работаю с пользовательским подклассом Thread (назовем его SwallowingThread), который проглатывает ряд исключений в его осуществлении Thread.run() аналогичны следующий код:Обнаружение записи в стандартный поток ошибок

public final class SwallowingThread extends Thread { 

    ... 

    @Override 
    public void run() { 
     ServerSocket socket = new ServerSocket(80, 100); 
     try { 
      Socket connected = socket.accept(); 
      // Do stuff with socket here 
     } catch (UnknownHostException e) { 
      e.printStackTrace(); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 
    } 
} 

В моем коде, однако , Я хочу иметь возможность обрабатывать случаи UnknownHostException и IOException, которые возникают при использовании экземпляра SwallowingThread; Невозможно ли обнаружить, что эта уловка и печать стандартная ошибка после ее возникновения? — Я изначально пробовал написать UncaughtExceptionHandler, чтобы сделать это, чтобы узнать, что он не ловит исключения, потому что они были проглочены, а не просто были, например. завернутый в RuntimeException и брошенный вперед.

Конечно, «лучший» способ решения этой проблемы - переписать логику для класса, но нет ли быстрого и грязного способа решения этой проблемы без необходимости касаться SwallowingThread?

+2

Вы можете создать 'PrintStream', что Обертывания' Возможно, System.err'? 'System.setErr (новый MyDelegatingPrintStream (System.err));' –

+1

Возможный дубликат [Redirect System.out и System.err] (http://stackoverflow.com/questions/14715748/redirect-system-out-and- system-err) –

+0

@MuratK, нет, я не хочу просто помещать данные, которые были введены в stderr в другое место: я хочу иметь возможность выполнить некоторую логику один раз/если эти данные записываются в stderr. – errantlinguist

ответ

4

Вы можете реализовать свой собственный класс (я называю это DelegatingErrorPrintStream), полученный из PrintStream который уведомляет вас, если есть новый выход, а затем делегаты System.err И теперь вы можете установить DelegatingErrorPrintStream в качестве выходного потока для System.err использования System.setErr (err);

Полный пример включая использование:

import java.io.FileNotFoundException; 
import java.io.PrintStream; 
import java.io.UnsupportedEncodingException; 

public class ErrorNotifierExample { 
private static final class ErrorDelegatingPrintStream extends PrintStream { 
    public ErrorDelegatingPrintStream(PrintStream defaultErr) 
      throws FileNotFoundException, UnsupportedEncodingException { 
     super(defaultErr); 
    } 

    @Override 
    public void print(boolean b) { 
     super.print(b); 
     notifyListener(b); 
    } 

    @Override 
    public void print(char c) { 
     super.print(c); 
     notifyListener(c); 
    } 

    @Override 
    public void print(int i) { 
     super.print(i); 
     notifyListener(i); 
    } 

    @Override 
    public void print(long l) { 
     super.print(l); 
     notifyListener(l); 
    } 

    @Override 
    public void print(float f) { 
     super.print(f); 
     notifyListener(f); 
    } 

    @Override 
    public void print(double d) { 
     super.print(d); 
     notifyListener(d); 
    } 

    @Override 
    public void print(char[] s) { 
     super.print(s); 
     notifyListener(s); 
    } 

    @Override 
    public void print(String s) { 
     super.print(s); 
     notifyListener(s); 

    } 

    @Override 
    public void print(Object obj) { 
     super.print(obj); 
     notifyListener(obj); 

    } 

    @Override 
    public PrintStream append(CharSequence csq, int start, int end) { 
     notifyListener(csq); // TODO will need some special handling 
     return super.append(csq, start, end); 
    } 

    private void notifyListener(Object string) { 
     // TODO implement your handling here. System.out printing is just an 
     // example. 
     System.out.println(String.valueOf(string)); 
    } 
} 

public static void main(String[] args) throws FileNotFoundException, UnsupportedEncodingException { 
    ErrorDelegatingPrintStream errReplacement = new ErrorDelegatingPrintStream(System.err); 
    System.setErr(errReplacement); 

    System.err.println("TEST01"); 
    throw new RuntimeException("just a test output for ERROR handling"); 
} 
} 
+0

Все эти ответы были отличными, но это было почти так, как я закончил (в частности, передав «Customer » в качестве делегата вместо вашей логики 'notifyListener (Object)». – errantlinguist

2

Как несколько людей уже предложили, вы можете пойти с обычаем PrintStream.

Он заменит стандартный поток ошибок, а также инкапсулирует его и называет его при необходимости.

Поскольку исключения и следы стекол - это то, что вас интересует, переопределения print(String) должно быть достаточно (println(String) уже называет этот метод + newLine()).

поток может выглядеть так:

import java.io.PrintStream; 

public class CustomPrintStream extends PrintStream { 


    public CustomPrintStream(final PrintStream out) { 

     super(out); 

    } 

    @Override 
    public void print(final String s) { 

     super.print(s); 
     // some String is written to the error stream, Do something ! 

    } 

} 

Вы могли бы использовать его таким образом, в начале вашего приложения, просто вызовите

System.setErr(new CustomPrintStream(System.err));