【问题标题】:How to save the output of a console application如何保存控制台应用程序的输出
【发布时间】:2008-09-14 03:50:10
【问题描述】:

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

当我没有找到更简洁的方法时,我使用的解决方法是将TextWriter 子类化,覆盖写入方法,这样它们既可以写入文件,又可以调用原始的标准输出写入器。像这样的:

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
    }
  }
}

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

另外,请原谅上述代码的不准确之处(不得不写它临时,抱歉;)。

【问题讨论】:

    标签: c# .net console stdout


    【解决方案1】:

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

    【讨论】:

    • 好主意!事实上,我需要的是一个记录器。这样,我可以存储比简单地向用户显示的信息更多的信息(并且更少地打扰他)。很多时候,最好的解决方案来自不同的方法,来自问题之外的人。
    • 我认为在这种情况下,使用 3rd 方库可能只需要少量工作即可为系统添加必要的功能。
    • 我同意 log4net 是一个非常严重的依赖项。
    • 这感觉更像是一种 hack,而不是问题中提出的方法。
    • 好点。我这周回去工作时会检查这笔费用。我在这里找到的主要优点是更容易将调试信息保存在文件中,而无需将其显示在屏幕上。此外,串行 I/O 是我项目的主要瓶颈。
    【解决方案2】:

    我不认为你的方法有什么问题。

    如果您想要可重用代码,请考虑实现一个名为 MultiWriter 的类或类似的类,该类将两个(或 N 个?)TextWriter 流作为输入并将所有命令、刷新等分配给这些流。然后你可以做这个文件/控制台的事情,但是你可以很容易地分割任何输出流。有用!

    【讨论】:

    • 我的方法的问题是我一直保持文件打开并刷新它。而且,我想,在每次写入时打开和关闭文件会很麻烦。不过,您对 MultiWriter 的想法非常聪明 :)
    【解决方案3】:

    可能不是你想要的,但以防万一……显然,PowerShell implements 是古老的tee 命令的一个版本。这几乎就是为了这个目的。所以......如果你有他们,就抽他们。

    【讨论】:

      【解决方案4】:

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

      创建一个“输出”类,它可以有不同的类来遵守文本输出接口。您向输出类报告,它会自动将给定的输出发送给您添加的类(ConsoleOutput、TextFileOutput、WhateverOutput)。等等。这也让您可以添加其他“输出”类型(例如 xml/ xslt 以获得格式良好的报告?)。

      查看Trace Listeners Collection 了解我的意思。

      【讨论】:

        【解决方案5】:

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

        对于您在此处尝试解决的特定问题,用户交互部分可以直接将其行为从 Console.WriteLine 更改为文件 I/O。

        【讨论】:

          【解决方案6】:

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

          如果您仍在尝试通过保存控制台输出在自己的代码中执行此操作(而不是使用日志系统仅保存您真正关心的信息),我认为您可以避免每次写入后刷新,只要您还覆盖 Flush() 并确保它刷新您保存的原始 stdoutWriter 以及您的 fileWriter。如果应用程序试图将部分行刷新到控制台以立即显示(例如输入提示、进度指示器等),您希望这样做,以覆盖正常的行缓冲。

          如果该方法存在控制台输出缓冲时间过长的问题,您可能需要确保 WriteLine() 刷新 stdoutWriter(但可能不需要刷新 fileWriter,除非您的 Flush() 覆盖叫做)。但我认为原来的Console.Out(实际上是在控制台)会自动刷新它的缓冲区换行,所以你不应该强迫它。

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

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2019-09-10
            • 2011-03-10
            • 1970-01-01
            • 1970-01-01
            • 2010-12-22
            • 1970-01-01
            相关资源
            最近更新 更多