console.setout重定向到文件最简方式是用using包裹streamwriter并缓存恢复原输出流;redirectstandardoutput用于拦截外部进程输出;需注意编码、线程安全及适用场景。

Console.SetOut 重定向到文件最简方式
直接用 Console.SetOut 替换默认输出流,是 C# 控制台程序保存输出最轻量的方案。它不改原有 Console.WriteLine 调用,也不需要逐行写文件。
常见错误是忘记关闭 StreamWriter,导致文件内容没刷出、末尾缺失;或者用完没恢复原 Console.Out,影响后续调试输出。
- 必须用
using块包裹StreamWriter,确保Dispose()触发刷新和关闭 - 如果程序中其他地方还依赖控制台输出(比如日志、调试语句),重定向前先缓存原始
Console.Out,结束后手动恢复 - 路径用相对路径时,实际写入位置取决于启动目录,不是项目根目录或 exe 所在目录
var originalOut = Console.Out;
using (var file = new StreamWriter("output.txt"))
{
Console.SetOut(file);
Console.WriteLine("这行会进TXT");
Console.WriteLine("这行也是");
} // ← 此处自动 Flush + Close
Console.SetOut(originalOut); // 恢复控制台输出
RedirectStandardOutput 需要 Process.Start 的场景
当你调用的是外部命令(比如 dotnet build、git status),而不是自己代码里的 Console.WriteLine,就得靠 ProcessStartInfo.RedirectStandardOutput = true 拦截子进程输出。
容易踩的坑是只设了重定向却忘了读取 process.StandardOutput,结果子进程卡死(管道缓冲区满);或者用 ReadToEnd() 阻塞等待,但子进程没退出就永远等下去。
- 务必在
process.Start()后立即开始读取,推荐用BeginOutputReadLine()+ 事件回调,避免阻塞 - 别漏掉
RedirectStandardError = true,否则错误信息仍打到控制台,看起来像“没重定向成功” - Windows 下 cmd/powershell 的编码可能不是 UTF-8,读取时需显式指定
Encoding.Default或Encoding.GetEncoding(936)(GBK)
StreamWriter 构造函数里 encoding 参数很关键
中文乱码不是因为没保存,而是保存时用了系统默认编码(如 GBK),但你用记事本/VS Code 默认以 UTF-8 打开 —— 两者对不上。
尤其在 Windows 中文系统下,new StreamWriter("log.txt") 默认用 Encoding.Default(通常是 GBK),而现代编辑器默认 UTF-8,打开就是乱码。
- 明确传
Encoding.UTF8:new StreamWriter("log.txt", false, Encoding.UTF8) - 第二个参数
false表示不追加(覆盖写),true才是追加 —— 很多人误以为默认覆盖,其实默认是追加 - UTF-8 不带 BOM 更通用,
Encoding.UTF8默认不带 BOM;若需 BOM,得用new UTF8Encoding(true)
异步写入时 Console.SetOut 不安全
如果程序里混用了 Console.WriteLine 和 await File.WriteAllTextAsync 等异步操作,再用 Console.SetOut 就可能出问题:多个线程/上下文共用一个 TextWriter 实例,写入错乱或抛 ObjectDisposedException。
这不是 .NET Bug,而是 StreamWriter 默认非线程安全,且 Console.SetOut 是全局静态操作,无法隔离作用域。
- 纯同步控制台程序,
Console.SetOut完全够用 - 含 async/await、多线程、或 WebHost 场景,改用显式
StreamWriter+await writer.WriteLineAsync(),绕过Console全局状态 - 别试图在 async 方法里临时 SetOut 再恢复 —— await 切上下文后,恢复操作可能失效或作用于错误线程
重定向本身很简单,难的是判断该用哪一层:是改自己代码的输出流,还是捕获子进程输出,又或者要兼容异步和多线程。选错一层,后面全是隐性 bug。











