将 Console.Out 写入不同的输出文件

3
我正在尝试使用 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将输出重定向到不同的文件中?
编辑1:程序在没有任何错误的情况下终止,这是否保证所有文件流都已关闭和刷新?
编辑2:感谢每一个回答我的问题的人,我能够找到解决方案,而不需要改变代码并添加两行额外的代码来关闭文件流。 Console.Out.Close(); 有人能解释一下为什么程序终止后文件流没有被关闭和刷新吗?
7个回答

6
如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");

这将会在控制台中打印出来:
Real 1
Real 2

它将追加到 Foo.txt 文件中:
Moo
Bar

它将会追加到Bar.txt文件中:
Ork

非常好的写入文本文件的解决方案 :)。 - Rozuur

2

这是一个非常奇怪的情况——我认为你应该只有两个不同的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会失败吗? - Rozuur
你是否按建议将AutoFlush属性设置为true了? - user595010
@djeeg 如果程序在控制台写入后终止,它会负责关闭流,对吗?@Rest Wing 因为我没有创建任何对象,所以无法设置AutoFlush属性。 - Rozuur
@Rest wing 谢谢,它解决了我的问题,但我不想创建一个变量。 - Rozuur
@Marc Gravell:看看我的解决方案,你可能会喜欢 :) - leppie
显示剩余2条评论

2
    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");
        }
    }

2

将通过 System.IO.File.CreateText 返回的每个 System.IO.StreamWriterAutoFlush 属性设置为 true


2

1

编辑:修改后,您可以将不同的字符串写入不同的文件中。

你不能编写一个包装类来为你完成这个吗?

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
这将是我所需的过度杀伐。 - Rozuur
@Marc Gravell,修改为使用字典并为每个文件命名令牌,从而方便此操作 :P - Moo-Juice
为什么为什么为什么?File.AppendAllText已经可以做到这一点了!请查看我的回答中的注释。 - leppie
@leppie,谢谢你。我不知道AppendAllText - Moo-Juice

1
有人能解释一下为什么程序终止后文件流没有被关闭和刷新吗?
当资源最终被处理时,文件的句柄会被释放。通过显式地关闭文件句柄,您可以保证释放发生的时间(而不是保证释放是否发生——如果由框架处理,它最终会发生)。
因此,始终显式地关闭文件句柄,以便您知道您占用文件的时间尽可能短。

抱歉,我应该编辑我的问题,改为为什么在关闭后没有刷新。 - Rozuur

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接