【问题标题】:Writing Console.Out to different output files将 Console.Out 写入不同的输出文件
【发布时间】:2011-02-02 10:36:55
【问题描述】:

我正在尝试使用 Console.SetOutConsole.Out 重定向到两个文本文件。

Console.SetOut(File.CreateText("c:\\del1.txt"));
Console.WriteLine(string1);
...
Console.SetOut(File.CreateText("c:\\del2.txt"));
Console.WriteLine(string2);

通过这种重定向,创建了两个没有任何数据的文本文件。如果我注释掉第二个重定向,这很好用。如何使用Console.SetOut 将输出重定向到不同的文件。

Edit1:程序终止时没有任何错误,这是否可以保证所有文件流都已关闭并刷新?

编辑2: 感谢所有回答我问题的人,我能够在不更改代码并添加两行额外行来关闭文件流的情况下找到解决方案。 Console.Out.Close();

谁能解释为什么程序终止后文件流没有关闭和刷新?

【问题讨论】:

    标签: c# stdout


    【解决方案1】:

    正如 Marc 所指出的,您希望不同的文件使用不同的字符串。为什么不每次通话都使用File.AppendAllText

    您也可以通过使用using 构造来执行诸如动态绑定之类的操作。

    更新:

    一个简单的动态绑定:

    class DynamicConsole : TextWriter
    {
      readonly TextWriter orig;
      readonly TextWriter output;
    
      public DynamicConsole(string filename)
      {
         orig = Console.Out;
        output = File.AppendText(filename);
        Console.SetOut(output);
      }
    
      public override System.Text.Encoding Encoding
      {
        get { return output.Encoding; }
      }
    
      public override void Write(char value)
      {
        output.Write(value);
      }
    
      protected override void Dispose(bool disposing)
      {
        Console.SetOut(orig);
        output.Dispose();
      }
    }
    

    用法(嵌套也可以):

    Console.WriteLine("Real 1");
    
    using (new DynamicConsole("Foo.txt"))
    {
      Console.WriteLine("Moo");
    
      using (new DynamicConsole("Bar.txt"))
      {
        Console.WriteLine("Ork");
      }
    
      Console.WriteLine("Bar");
    }
    
    Console.WriteLine("Real 2");
    

    这将打印到Console:

    Real 1
    Real 2
    

    它将附加到Foo.txt:

    Moo
    Bar
    

    它将附加到Bar.txt:

    Ork
    

    【讨论】:

    • 非常好的写入文本文件的解决方案:)。
    【解决方案2】:

    移至跟踪功能,并将 ConsoleTraceListener 添加为侦听器之一。然后使用 TextWriterTraceListener 添加您的文本文件。

    使用跟踪开关重定向到一个或另一个侦听器。

    更多解释可以在这里找到http://msdn.microsoft.com/en-us/library/system.diagnostics.traceswitch.aspx

    【讨论】:

      【解决方案3】:

      这是一个非常奇怪的场景 - IMO 你应该只有两个不同的TextWriter,并在需要时写信给他们。不理会控制台。如果调用者想要通过管道传输标准输出,让他们通过命令 shell 担心。

      using(var file = File.CreateText(@"c:\del1.txt")) {
          file.WriteLine(string1);
      }
      using(var file = File.CreateText(@"c:\del2.txt")) {
          file.WriteLine(string2);
      }
      

      如果这意味着更改一些现有代码以传入TextWriter,那么这纯粹是一件好事。

      【讨论】:

      • 是的,我已经进行了这些更改以使用不同的文件流,但知道为什么 SetOut 失败了吗?
      • 我不认为它失败了,你只是没有刷新文件流,所以你在文件中什么都看不到
      • 您是否按照建议将 AutoFlush 属性设置为 true?
      • @djeeg 如果程序在控制台写入后终止,它会负责关闭流,对吗? @Rest Wing 因为我没有创建任何对象,所以我无法设置 AutoFlush 属性。
      • System.IO.File.CreateText 创建该对象。只需将其放入变量中(或字段或属性,如果您以后需要再次使用它),然后设置属性。
      【解决方案4】:
          using (TextWriter file1 = File.CreateText("c:\\del1.txt")) {
              using (TextWriter file2 = File.CreateText("c:\\del2.txt")) {
                  Console.SetOut(file1);
                  Console.WriteLine("test1");
                  Console.SetOut(file2);
                  Console.WriteLine("test2");
              }
          }
      

      【讨论】:

        【解决方案5】:

        System.IO.File.CreateText 返回的每个 System.IO.StreamWriterAutoFlush 属性设置为 true强>。

        【讨论】:

          【解决方案6】:

          编辑:修改,以便您可以对不同的文件执行不同的字符串..

          你不能写一个包装类来为你做这件事吗?

          public class MyConsole
          {
              //private List<IO.StreamWriter> m_Outputs = new List<IO.StreamWriter>();
              private Dictionary<String, IO.StreamWriter> m_Outputs = new Dictionary<String, IO.StreamWriter>();
          
              public MyConsole() { }
              public MyConsole(string _token, string _file)
              {
                  AddOutput(_token, _file);
              }
          
              public void AddOutput(string _token, string _file)
              {
                  IO.StreamWriter writer = new IO.StreamWriter(_file)
                  m_Outputs[_token] = writer;
              }
          
              public void WriteLine(string _token, string _data)
              {
                  if(m_Outputs.ContainsKey(_token))
                      m_Outputs[_token].WriteLine(_data);
              }
          
          
              public void Close()
              {
                  foreach(KeyValuePair<String, IO.StreamWriter> pair in m_Outputs)
                      pair.Value.Close();
              }
          } // eo class MyConsole
          

          用法:

          MyConsole c = new MyConsole();  // or pass a file explicitly here
          c.AddOutput("file1", "C:\\file1.txt");
          c.AddOutput("file2", "C:\\file2.txt");
          c.WriteLine("file1", "Test!");
          c.WriteLine("file2", "Test2!");
          

          请注意,此代码未经测试,按原样编写,不暗示任何保证。 :P

          【讨论】:

          • 请注意,OP正在将不同的字符串写入两个不同的文件,而不是将相同的字符串写入多个文件。
          • 这对于我需要的东西来说太过分了。
          • @Marc Gravell,修改为使用字典并为每个文件命名标记,从而促进这一点:P
          • 为什么为什么为什么? File.AppendAllText 已经这样做了!请参阅我的答案注释。
          • @leppie,谢谢。我不知道AppendAllText
          【解决方案7】:

          谁能解释为什么文件流 后不关闭和冲洗 程序终止?

          最终释放资源时,文件的句柄最终会被释放。通过显式关闭文件句柄,您可以保证发布发生的时间(而不是保证发布发生 - 如果您将其留给框架,它最终会发生)。

          因此,请务必明确关闭您的文件句柄,以便您知道您已在尽可能短的时间内占用了一个文件。

          【讨论】:

          • 对不起,我应该编辑我的问题,为什么关闭后不刷新。
          猜你喜欢
          • 2012-12-23
          • 2012-07-13
          • 1970-01-01
          • 2019-04-04
          • 1970-01-01
          • 1970-01-01
          • 2014-09-16
          • 2015-04-09
          • 2012-08-02
          相关资源
          最近更新 更多