2014-12-12 17 views
7

Ben tercihen aynı anda, benim program istisnalar aşağıdakilerden her gönderilecek istiyorum:işleme tüm istisnalar

  • (şart değil) başlatır konsol
  • bir gui
  • bir txt dosyası.

Bunu nasıl başarabilirim?

denemelerim:

  • System.setErr(PrintStream err) yeni bir akışa tüm istisnaları iletecektir. Yine de bir akışından daha fazlasını belirtemiyorum. -

    Jeffrey Bosboom

    "Birden akışlarına iletir kendi akışı sınıfını yazmak ve bu sınıfın bir örneği System.setOut çağırabilir":

  • manuel OutputStream yazılı üzerinde System.setErr(PrintStream err) çağırma

    Bunu yapmanın bir yolunu buldum. Yine de çok kötü. Bu, PrintStream 'ın write -bytes "toplayan" Bir balığı (500 ms zaman aşımı) koyar ve sonunda kullanıcı (Proceed) bunu göstermektedir:

    /* ErrorOutput.java */ 
    public static t_ErrBuffer t_activeErrBuffer = new t_ErrBuffer(""); 
    public static void setStdErrToFile(final File file) { 
        ps = new PrintStream(fos) { 
         @Override 
         public void write(byte[] buf, int off, int len) { 
          byte[] bn = new byte[len]; 
          for (int i = off, j = 0; i < (len + off); i++, j++) { 
           bn[j] = buf[i]; 
          } 
          String msg = null; 
          try { 
           msg = new String(bn, "UTF-8"); 
          } catch (UnsupportedEncodingException e1) {} 
          if (msg.matches("[\\w\\W]*[\\w]+[\\w\\W]*")) { // ^= contains at least one word character 
           if(! t_activeErrBuffer.isAlive()) { 
            t_activeErrBuffer = new t_ErrBuffer(msg); 
            t_activeErrBuffer.start(); 
           } else { 
            t_activeErrBuffer.interrupt(); 
            t_activeErrBuffer = new t_ErrBuffer(t_activeErrBuffer.getErrBuffer() + "\n" + msg); // ^= append to buffer and restart. 
            t_activeErrBuffer.start(); 
           } 
          } 
         } 
        }; 
        System.setErr(ps); 
    } 
    
    /* t_ErrBuffer.java */ 
    public class t_ErrBuffer extends Thread { 
        private String errBuffer; 
        public t_ErrBuffer(String buffer) { 
         this.errBuffer = buffer; 
        } 
        protected class Proceed implements Runnable { 
         public String msg = null; 
         public Proceed(String msg) { 
          this.msg = msg; 
         } 
         @Override 
         public void run() { 
          // todo PRINT ERROR MESSAGE: DO THINGS WITH msg: console, gui, JOptionPane 
         } 
        } 
        @Override 
        public void run() { 
         try { 
          Thread.sleep(500); // collect error lines before output. Needed because PrintStream's "write"-method writes ErrorMessages in multiple pieces (lines) 
          // each time some new exception line comes in, the thread is stopped, buffer is being appended and thread new started 
         } catch (InterruptedException e) { 
          return; // stop 
         } 
         // after 500 ms of wait, no new error message line has come in. Print the message out: 
         Thread t_tmp = new Thread(new Proceed("\n" + this.errBuffer)); 
         t_tmp.start(); 
         return; 
        } 
        public String getErrBuffer() { 
         return this.errBuffer; 
        } 
    } 
    

    bu benim yapmak bekleniyor am nedir?

  • Benim için bunu yapan yeni istisna sınıfı oluştur. Yakalamak-blok/misiniz muhtemelen çalışır, ama bunun dışında istisnalar (IO, FileNotFound, ...) hala eski yol

  • Onun yerine denemede benim kod tüm içine olabilir [method name] throws Exception belirten

    tutulacaktır istisna almak ve bunun gibi, benim bir yönteme iletiriz:

    /* AnyMethod.java */ 
    // ... 
    try { 
        // ... do everything here 
    } catch (IOException | FileNotFoundException e) { // as many as you like 
        ErrorOutput.crash(e); 
    } 
    // ... 
    
    /* ErrorOutput.java */ 
    public static void crash(Exception e) { 
        FileOutputStream fos_errOutput = new FileOutputStream(new File("ErrorOutput.txt"), true); 
    
        // 1st 
        if (!System.out.equals(fos_errOutput)) { 
         System.out.println(e.getMessage() + " :"); // to console or the preferred StdOut 
         e.printStackTrace(); 
        }  
    
        // 2nd 
        JOptionPane.showMessageDialog(Gui.frame, "THE PROGRAM HAS CRASHED!" + "\n\n" + e.getMessage() + "\n\nFor a more detailed report, see ErrorLog.txt"); // gui output 
    
        // 3rd 
        PrintStream ps = new PrintStream(fos_errOutput); 
        ps.print(new Date().toString() + ":"); // write to file 
        e.printStackTrace(ps); 
        ps.close(); 
    
        // 4th 
        System.exit(0); // this could also be "throw new Exception" etc., but I don't know why one should do that. 
    } 
    

    bu muhtemelen de çalışacak, yakalamam-blok/denemede içine herşeyi sokmanız gerekiyor. Bu iyi bir programlama tarzı olamaz. Sadece yardım Korku Wombat

    zararlılarına -

    "kullanım log4j ve kurmak bir yöntem GUI yazmaya ve ayrıca Stdout'a oturum açmak için ve dosya":

  • bir logger kullanma yazdırma İstisnalarım akışa istedim, ama onları yakalamama yardım etmiyorlar, değil mi?

    Ancak bunun için bir günlük paketi kullanmalısınız - hatta java.util.günlük ihtiyacınız ne yapabilirim - Jeffrey Bosboom

    benim günlük paket nerede ve ne giriş yapmak için söylemek zorundayım. Ama bu tam olarak aradığım şey. user3159253 önerildiği gibi

Şimdi, özellikle özel duruma yakalamak için Thread.UncaughtExceptionHandler kullanabilirsiniz.

tüm atılan özel durumları istediğim şekilde işlemek için doğru yol nedir?Thread.UncaughtExceptionHandler ve System.setErr()'dan başka nelere dikkat etmeliyim (yukarıya bakın)?

+3

log4j'yi kullanın ve GUI'ye yazmak için bir yöntem ayarlayın ve ayrıca stdout'a oturum açın ve –

+0

dosyasını gönderin Kendi akış sınıfınızı birden çok akışa iletebilir ve bu sınıfın bir örneğinde 'System.setOut' çağrısı yapabilirsiniz. (Ama bunun için bir günlük paketi kullanmalısınız - java.util.logging bile ihtiyacınız olan her şeyi yapabilir, hiçbir bağımlılık gerekmez.) –

+0

Benzer şekilde [slf4j] gibi standart bir kayıt özelliğini kullanmanız gerekir (http: // www .slf4j.org /) veya daha önce bahsedilen [log4j] (http://logging.apache.org/log4j/2.x/) ve bir [Thread.UncoughtExceptionHandler] (http://docs.oracle.com/javase /7/docs/api/java/lang/Thread.UncaughtExceptionHandler.html) http://stackoverflow.com/questions/2344654/log-runtime-exceptions-in-java-using-log4j – user3159253

cevap

5

Önce iş parçanızdan/içeriden atılan tüm istisnai durumları beklemeniz gerekir (deneme/yakalama veya Thread.UncoughtExceptionHandler veya ThreadPoolExecutor.afterExecute(Runnable r, Throwable t)).

Sonra istisna örneğiniz olduğunda log4j kullanarak oturum açabilir, ancak Log4j ekleyicilerini özel durum iletilerinizi birden çok hedefe göndermek için yapılandırabilirsiniz. İhtiyacınıza bağlı olarak, Dosya, Konsol, JDBC, JMS vb ek türlerini kullanabilirsiniz. Ayrıca Async appender ile onları sarmak en iyisidir.

bakın - https://logging.apache.org/log4j/2.x/manual/appenders.html

GUI istisnası mesaj iterek hakkında, senin uygulamanızda kullanırken hangi teknoloji yığını bağlı olarak çeşitli şekillerde uygulanabilir. Bizim uygulamada, olay olaylarını (sadece kritik olanları) veritabanında saklamaktayız, bunlar daha sonra sunucudan olay izleme konuları tarafından toplanmakta ve daha sonra http://cometd.org/documentation/cometd-java kullanılarak GUI'ye (JQuery, JavaScript) geri gönderilmektedir.

2

PrintStream'u genişleten bir nesne oluşturulmalıdır. Her ne zaman bir satır alırsa, onu görüntüleyebilir ve gerektiğinde kaydedebilir. Alternatif olarak, tüm istisnalar yakalanabilir ve bir parametre olarak bir Exception alan bir yönteme yönlendirilebilir ve yöntem istisnayı günlüğe kaydetme/gösterme ve programı düzgün bir şekilde sonlandırma ile ilgilenebilir.