C# 将处理结果重定向到文本文件
C# Redirecting process results to a text file
我一直在绞尽脑汁想弄清楚为什么我不能使用 >>(追加)作为我 p.StartInfo.Argument 的一部分。当我删除“>”时,它工作得很好,但当我尝试使用“>”或“>>”时,我收到 "Incorrect Parameter" 错误。我已经继续编写没有 > 或 >> 的程序,只是将输出存储到一个字符串中,稍后将其写入文件。有人可以解释为什么“>”或“>>”在这种情况下不起作用吗?
// Start the child process.
Process p = new Process();
// Redirect the output stream of the child process.
p.StartInfo.UseShellExecute = false;
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.FileName = "attrib.exe";
startInfo.Arguments = "/S *.jpg > mypics.txt";
p.Start();
那是因为 >
和 >>
不是 attrib.exe
解释的参数,它们是 cmd.exe
.
的指令
你可以试试这样的东西:
p.StartInfo.FileName = "cmd.exe";
p.StartInfo.Arguments = "/c attrib.exe /S *.jpg > mypics.txt";
此外,这是一条红鲱鱼:
p.StartInfo.RedirectStandardOutput = true;
如果您想以 C# 代码读取输出并自己编写文件,则可以使用此选项。使用 >
输出重定向器没有帮助。
输出重定向运算符 >
是 cmd.exe
的功能,而不是操作系统。因此,使用它的天真方法是这样调用 cmd
:
p.StartInfo.FileName = "cmd.exe";
startInfo.Arguments = "/C \"attrib.exe /S *.jpg > mypics.txt\"";
但是,重定向输出的正确方法是首先将 StartInfo.RedirectStandardOutput
设置为 true
(您这样做了),然后将 Process.StandardOutput
的输出通过管道传输到文件,因此:
using(StreamWriter file = new StreamWriter("mypics.txt")) {
p.StandardOutput.CopyTo(file);
}
或者,异步版本:
using(StreamWriter file = new StreamWriter("mypics.txt")) {
await p.StandardOutput.CopyToAsync(file);
}
SlugFiller 的解决方案很好,但不能可靠地处理大量输出。问题是,如果进程输出太多文本,它就会挂起,因为流达到了最大缓冲区大小。换句话说,流需要在进程运行时被假脱机,防止缓冲区被填满。
但是,有一种方法可以使用任务从输出流接收数据并在 real-time 中将其假脱机出来。
// Start the child process.
Process p = new Process();
// Redirect the output stream of the child process.
p.StartInfo.UseShellExecute = false;
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.FileName = "attrib.exe";
startInfo.Arguments = "/S *.jpg > mypics.txt";
p.Start();
Thread stdoutThread = new Thread(new ThreadStart(WriteStandardOutput));
stdoutThread.IsBackground = true;
stdoutThread.Name = "stdout_writer";
stdoutThread.Start();
private void WriteStandardOutput()
{
using (StreamWriter sw = File.CreateText(ConsoleLogFileFullPath))
using (StreamReader sr = p.StandardOutput)
{
for (;;)
{
string line = sr.ReadLine();
if (line == null)
break;
sw.WriteLine(textLine);
}
sw.Flush();
}
}
在某些时候一定要调用 stdoutThread.Join()
以确保线程完成。我已经用一些生成大量输出的代码对此进行了测试,它仍然有可能溢出缓冲区,或者用极长的行打破 ReadLine()
,但它确实适用于几千个数量级的非常快的输出每秒 80 个字符行。
我一直在绞尽脑汁想弄清楚为什么我不能使用 >>(追加)作为我 p.StartInfo.Argument 的一部分。当我删除“>”时,它工作得很好,但当我尝试使用“>”或“>>”时,我收到 "Incorrect Parameter" 错误。我已经继续编写没有 > 或 >> 的程序,只是将输出存储到一个字符串中,稍后将其写入文件。有人可以解释为什么“>”或“>>”在这种情况下不起作用吗?
// Start the child process.
Process p = new Process();
// Redirect the output stream of the child process.
p.StartInfo.UseShellExecute = false;
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.FileName = "attrib.exe";
startInfo.Arguments = "/S *.jpg > mypics.txt";
p.Start();
那是因为 >
和 >>
不是 attrib.exe
解释的参数,它们是 cmd.exe
.
你可以试试这样的东西:
p.StartInfo.FileName = "cmd.exe";
p.StartInfo.Arguments = "/c attrib.exe /S *.jpg > mypics.txt";
此外,这是一条红鲱鱼:
p.StartInfo.RedirectStandardOutput = true;
如果您想以 C# 代码读取输出并自己编写文件,则可以使用此选项。使用 >
输出重定向器没有帮助。
输出重定向运算符 >
是 cmd.exe
的功能,而不是操作系统。因此,使用它的天真方法是这样调用 cmd
:
p.StartInfo.FileName = "cmd.exe";
startInfo.Arguments = "/C \"attrib.exe /S *.jpg > mypics.txt\"";
但是,重定向输出的正确方法是首先将 StartInfo.RedirectStandardOutput
设置为 true
(您这样做了),然后将 Process.StandardOutput
的输出通过管道传输到文件,因此:
using(StreamWriter file = new StreamWriter("mypics.txt")) {
p.StandardOutput.CopyTo(file);
}
或者,异步版本:
using(StreamWriter file = new StreamWriter("mypics.txt")) {
await p.StandardOutput.CopyToAsync(file);
}
SlugFiller 的解决方案很好,但不能可靠地处理大量输出。问题是,如果进程输出太多文本,它就会挂起,因为流达到了最大缓冲区大小。换句话说,流需要在进程运行时被假脱机,防止缓冲区被填满。
但是,有一种方法可以使用任务从输出流接收数据并在 real-time 中将其假脱机出来。
// Start the child process.
Process p = new Process();
// Redirect the output stream of the child process.
p.StartInfo.UseShellExecute = false;
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.FileName = "attrib.exe";
startInfo.Arguments = "/S *.jpg > mypics.txt";
p.Start();
Thread stdoutThread = new Thread(new ThreadStart(WriteStandardOutput));
stdoutThread.IsBackground = true;
stdoutThread.Name = "stdout_writer";
stdoutThread.Start();
private void WriteStandardOutput()
{
using (StreamWriter sw = File.CreateText(ConsoleLogFileFullPath))
using (StreamReader sr = p.StandardOutput)
{
for (;;)
{
string line = sr.ReadLine();
if (line == null)
break;
sw.WriteLine(textLine);
}
sw.Flush();
}
}
在某些时候一定要调用 stdoutThread.Join()
以确保线程完成。我已经用一些生成大量输出的代码对此进行了测试,它仍然有可能溢出缓冲区,或者用极长的行打破 ReadLine()
,但它确实适用于几千个数量级的非常快的输出每秒 80 个字符行。