Question

J'ai besoin de conseils sur la façon dont mon application console C# affiche du texte à l'utilisateur via la sortie standard tout en pouvant y accéder plus tard.La fonctionnalité réelle que je voudrais implémenter est de vider l'intégralité du tampon de sortie dans un fichier texte à la fin de l'exécution du programme.

La solution de contournement que j'utilise même si je ne trouve pas d'approche plus propre consiste à sous-classer TextWriter en remplaçant les méthodes d'écriture afin qu'elles écrivent toutes les deux dans un fichier et appellent l'enregistreur de sortie standard d'origine.Quelque chose comme ça:

public class DirtyWorkaround {
  private class DirtyWriter : TextWriter {
    private TextWriter stdoutWriter;
    private StreamWriter fileWriter;

    public DirtyWriter(string path, TextWriter stdoutWriter) {
      this.stdoutWriter = stdoutWriter;
      this.fileWriter = new StreamWriter(path);
    }

    override public void Write(string s) {
      stdoutWriter.Write(s);

      fileWriter.Write(s);
      fileWriter.Flush();
    }

    // Same as above for WriteLine() and WriteLine(string),
    // plus whatever methods I need to override to inherit
    // from TextWriter (Encoding.Get I guess).
  }

  public static void Main(string[] args) {
    using (DirtyWriter dw = new DirtyWriter("path", Console.Out)) {
      Console.SetOut(dw);

      // Teh codez
    }
  }
}

Vérifiez qu'il écrit et vide le fichier à tout moment.J'adorerais le faire uniquement à la fin de l'exécution, mais je n'ai trouvé aucun moyen d'accéder au tampon de sortie.

Excusez également les inexactitudes avec le code ci-dessus (j'ai dû l'écrire ad hoc, Désolé ;).

Était-ce utile?

La solution

La solution idéale pour cela est d'utiliser log4net avec un ajout de console et un ajout de fichiers.De nombreux autres appendeurs sont également disponibles.Il vous permet également d'activer et de désactiver les différents appenders au moment de l'exécution.

Autres conseils

Je ne pense pas qu'il y ait quelque chose de mal dans votre approche.

Si vous souhaitez du code réutilisable, envisagez d'implémenter une classe appelée MultiWriter ou quelque chose qui prend comme entrée deux (ou N ?) TextWriter diffuse et distribue tous les brefs, chasses d’eau, etc.à ces flux.Ensuite, vous pouvez faire cette chose fichier/console, mais tout aussi facilement, vous pouvez diviser n'importe quel flux de sortie.Utile!

Ce n'est probablement pas ce que vous voulez, mais juste au cas où...Apparemment, Implémentations PowerShell une version du vénérable tee commande.Ce qui est à peu près destiné exactement à cet effet.Donc...fumez-les si vous les avez.

Je dirais d'imiter les diagnostics utilisés par .NET lui-même (Trace et Debug).

Créez une classe « de sortie » pouvant avoir différentes classes adhérant à une interface de sortie de texte.Vous faites rapport à la classe de sortie, elle envoie automatiquement la sortie donnée aux classes que vous avez ajoutées (ConsoleOutput, TextFileOutput, AnywhereOutput).Et ainsi de suite..Cela vous laisse également la possibilité d'ajouter d'autres types de « sortie » (tels que xml/xslt pour obtenir un rapport bien formaté ?).

Vérifiez Collection d'écouteurs de trace pour voir ce que je veux dire.

Envisagez de refactoriser votre application pour séparer les parties d'interaction utilisateur de la logique métier.D'après mon expérience, une telle séparation est très bénéfique pour la structure de votre programme.

Pour le problème particulier que vous essayez de résoudre ici, il devient simple pour la partie interaction utilisateur de modifier son comportement de Console.WriteLine pour classer les E/S.

Je travaille sur la mise en œuvre d'une fonctionnalité similaire pour capturer la sortie envoyée à la console et l'enregistrer dans un journal tout en transmettant la sortie en temps réel à la console normale afin qu'elle ne casse pas l'application (par exemple.si c'est une application console !).

Si vous essayez toujours de le faire dans votre propre code en enregistrant la sortie de la console (au lieu d'utiliser un système de journalisation pour enregistrer uniquement les informations qui vous intéressent vraiment), je pense que vous pouvez éviter le vidage après chaque écriture, à condition que car vous remplacez également Flush() et assurez-vous qu'il vide l'original stdoutWriter vous avez économisé ainsi que votre fileWriter.Vous souhaitez faire cela au cas où l'application essaierait de vider une ligne partielle vers la console pour un affichage immédiat (comme une invite de saisie, un indicateur de progression, etc.), pour remplacer la mise en mémoire tampon de ligne normale.

Si cette approche pose des problèmes de mise en mémoire tampon trop longue de la sortie de votre console, vous devrez peut-être vous assurer que WriteLine() vide stdoutWriter (mais il n'est probablement pas nécessaire de vider la chasse d'eau fileWriter sauf lorsque votre remplacement Flush() est appelé).Mais je pense que l'original Console.Out (en fait, aller à la console) viderait automatiquement son tampon lors d'une nouvelle ligne, vous ne devriez donc pas avoir à le forcer.

Vous souhaiterez peut-être également remplacer Close() pour (vider et) fermer votre fileWriter (et probablement stdoutWriter également), mais je ne sais pas si cela est vraiment nécessaire ou si un Close() dans la base TextWriter émettrait un Flush() (que vous remplaceriez déjà) et vous pourriez compter sur la sortie de l'application pour fermer votre fichier.Vous devriez probablement tester qu'il est vidé à la sortie, pour être sûr.Et sachez qu'une sortie anormale (plantage) ne videra probablement pas la sortie mise en mémoire tampon.Si c'est un problème, rincer fileWriter sur une nouvelle ligne peut être souhaitable, mais c'est une autre boîte de Pandore délicate à résoudre.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top