2010-11-23 18 views
3

Dans ma base de code est le (très simplifié) suivant:Comment empêcher les flux sysout et syserr de se mélanger?

public static void main (String[] args) { 
    System.out.println("Starting application"); 
    try { 
     System.out.println("About to validate"); 
     validate(args); 
    catch (Exception e) { 
     e.printStackTrace(); 
    } 
} 

public static void validate(String[] args) { 
    System.out.println("Your first arg is " + args[0]); 
    if (someProblemWith(args)) { 
     System.out.println("Your args are wrong. It should be: ..."); 
     throw new BadArgsException(e); 
    } 
} 

Ce qui fonctionne très bien. Notez que mon exemple de code ci-dessus est artificiel et simplement destiné à afficher plusieurs instructions de journal avant l'exception et l'impression de trace de pile. Cela signifie souvent que ma dernière instruction de journalisation est perdue au milieu de la sortie de la trace de la pile. Existe-t-il une manière élégante de demander à l'instruction e.printStackTrace() d'attendre jusqu'à ce que System.out ait terminé son travail? Je cherche essentiellement le stacktrace à être la dernière chose imprimée quand une erreur se produit. Voici un exemple de sortie de mon programme ci-dessus:

java.lang.Throwable 
.... 
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) 
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) 
Your args are wrong. It should be: ... 
at java.lang.reflect.Method.invoke(Method.java:597) 
at org.eclipse.jdt.internal.jarinjarloader.JarRsrcLoader.main(JarRsrcLoader.java:56) 
+2

OMG! Vous avez traversé les cours d'eau! Inversion protonique totale! –

Répondre

1

Appelez e.printStackTrace(System.out);. Ou, si vous n'en avez besoin que pour le débogage, vous pouvez séparer la sortie et l'erreur du processus de la ligne de commande: .... 1>output.log 2>error.log

+0

Merci. Cela ressemble à l'option la plus facile. –

8

La raison pour laquelle vous voyez la trace de la pile en cours d'impression entre System.out.println() déclarations, est parce que System.out est tamponnées, alors que System.err (utilisé par trace de la pile) est unbuffered.

Si vous souhaitez que le texte soit affiché dans l'ordre exact dans lequel les choses se passent, vous devez "unbuffer" le System.out. Le moyen le plus simple est d'utiliser simplement System.err au lieu de System.out.

Sinon, appelez System.out.flush() avant que vos traces de pile ne se produisent dans les clauses catch.

Option 2: utilisez la classe Logger.

Option 3: Implémentez votre propre "tampon". En d'autres termes, d'abord tout écrire dans votre propre tampon, y compris les traces de la pile (en utilisant .toString() ou comme vous le souhaitez), puis dans le tampon catch vous propre tampon. (Ceci est un peu redondant puisque vous pouvez simplement vider le System.out de toute façon).

- == -

DE COMMENTAIRE

Bien sûr. La classe Logger peut être utilisée pour créer une expérience de journalisation beaucoup plus robuste et détaillée. C'est typiquement ce qui est fait dans les applications. Une instance de la classe Logger est extraite de la classe Logger (c'est un singleton), en prenant comme paramètre la classe à partir de laquelle sera utilisée. Ensuite, vous enregistrez les messages à l'aide de la méthode .log(). La bonne chose à propos de la classe Logger est que vous pouvez définir des niveaux dessus (exemple DEBUG, WARN ...) et vous êtes alors en mesure de filtrer/afficher uniquement ce que vous voulez. Les messages « log » sont alors affichés d'une manière uniforme dans la console, généralement sous la forme de:

2010-11-23 14:45:32,032 DEBUG [MyClass] Your message

Le format ci-dessus est de log4j, mais vous pouvez utiliser la norme Java Logger. La sortie devrait être similaire, peut-être un peu moins. Mais je suis sûr qu'il peut être configuré.

+0

Merci. Pouvez-vous développer "User the Logger class"? –