关于C#:如何保存控制台应用程序的输出

关于C#:如何保存控制台应用程序的输出

How to save the output of a console application

我需要有关如何让我的C#控制台应用程序通过标准输出向用户显示文本,同时仍然可以稍后访问它的建议。我要实现的实际功能是在程序执行结束时将整个输出缓冲区转储到文本文件中。

我找不到更干净的方法时要使用的解决方法是将TextWriter子类覆盖重写方法,以便它们都可以写入文件并调用原始的stdout编写器。像这样的东西:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
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
    }
  }
}

看到它一直在写入并刷新文件。我只想在执行结束时这样做,但是我找不到任何访问输出缓冲区的方法。

也请原谅上面的代码有误(必须是临时编写,对不起;)。


为此的理想解决方案是将log4net与控制台附加程序和文件附加程序一起使用。也有许多其他的附加程序。它还允许您在运行时关闭和打开不同的附加程序。


我认为您的方法没有任何问题。

如果您想要可重用的代码,请考虑实现一个名为MultiWriter的类,该类将两个(或N?)TextWriter流作为输入并将所有命令,刷新等分配给这些流。然后,您可以执行此文件/控制台操作,但是可以轻松拆分任何输出流。有用!


我想说的是模仿.NET本身使用的诊断(跟踪和调试)。

创建一个" output "类,该类可以具有遵循文本输出接口的不同类。您向输出类报告,它会自动将给定的输出发送给您已添加的类(ConsoleOutput,TextFileOutput,WhateverOutput)。等等。 xml / xslt以获得格式正确的报告?)。

查看跟踪侦听器集合以了解我的意思。


可能不是您想要的,但是以防万一...显然,PowerShell实现了一个受人尊敬的tee命令的版本。正是出于这个目的。所以...如果有,就抽烟。


我正在努力实现类似的功能,以捕获发送到控制台的输出并将其保存到日志,同时仍将输出实时传递到普通控制台,以免破坏应用程序(例如,如果它是控制台应用程序!)。

如果您仍想通过保存控制台输出(而不是使用日志记录系统仅保存您真正关心的信息)来用自己的代码执行此操作,那么我认为您可以避免每次刷新后都刷新写,只要您还重写Flush()并确保它刷新保存的原始stdoutWriterfileWriter。如果应用程序尝试将部分行刷新到控制台以立即显示(例如输入提示,进度指示器等),以覆盖常规行缓冲,则需要执行此操作。

如果该方法在控制台输出缓冲时间过长时遇到问题,则可能需要确保WriteLine()刷新stdoutWriter(但可能不需要刷新fileWriter,除非您的Flush()覆盖)。但是我认为原始的Console.Out(实际上是进入控制台)会自动在换行符上刷新其缓冲区,因此您不必强制使用它。

您可能还想覆盖Close()以(刷新并)关闭您的fileWriter(也可能是stdoutWriter),但是我不确定这是否是真正需要的,或者是Close基本TextWriter中的()将发出Flush()(您已经覆盖了),并且您可能依赖于应用程序退出来关闭文件。可以肯定的是,您可能应该测试它是否在退出时被刷新了。并且请注意,异常退出(崩溃)可能不会刷新缓冲的输出。如果这是一个问题,则可能需要在换行符上刷新fileWriter,但这是蠕虫可以解决的另一个棘手问题。


考虑重构您的应用程序,以将用户交互部分与业务逻辑分开。以我的经验,这样的分离对您的程序结构非常有益。

对于您要在此处解决的特定问题,用户交互部分将其行为从Console.WriteLine更改为文件I / O变得很简单。


推荐阅读