【问题标题】:How to deal with output from console applications that use control characters?如何处理使用控制字符的控制台应用程序的输出?
【发布时间】:2013-07-04 23:46:40
【问题描述】:

我想调用一个可执行文件(在我的例子中,这是 PNGOUT.exe)并从标准输出中获取它的输出。但结果很棘手 - 应用程序使用某种控制字符来替换以前打印的输出(显示进度),C# 类愉快地记录它们,当我想分析输出字符串时,我很头疼。 (我什至花了一段时间才弄清楚我的字符串发生了什么)

我正在使用以下方法调用可执行文件:

public static string RunPNGOut(string pngOutPath, string target) {
   var process = new Process {
      StartInfo = {
         UseShellExecute = false,
         RedirectStandardOutput = true,
         CreateNoWindow = true,
         FileName = pngOutPath,
         Arguments = '"' + target + '"'
      }
   };
   process.Start();

   var result = process.StandardOutput.ReadToEnd();

   process.WaitForExit();

   return result;
}

我需要使用不同的方法在控制台中仅捕获文本的最终状态,或者以某种方式摆脱result 中的控制字符(不仅仅是删除它们,而是将它们“应用”到字符串以实现最终外观)。怎么办?

【问题讨论】:

  • 控制字符是否被转义? (例如\\t 而不是\t)?
  • 如果我只是打印字符串,它看起来就像最终文本,所以我认为不,它们没有被转义。
  • 如果没有转义,那么 Base64 编码可能吗?基本上,您需要确定输入的性质。
  • 这是来自名为 PNGOUT 的控制台应用程序的纯文本输出。但它使用一些特殊字符(不可见)来覆盖以前写的文本。

标签: c# console console-application windows-console


【解决方案1】:

很可能,输出包含 \r,它只是将光标返回到当前行的开头。如果这是真的,那么您可以通过擦除当前行来相应地调整字符串。不过,这并不简单——您还必须覆盖上一行。我将编写一些代码,看看是否能找到解决方案。

编辑:这是我想出的解决方案 - 它经过了轻微测试。输出将在lines 变量中,您可以单独分析,也可以将其合并为一行进行分析。

string rawOut = "Results:\r\n___ % done\r 10\r 20\r 30\r\nError!";
string[] lines = Regex.Split(rawOut, Environment.NewLine);
for(int j=0; j<lines.Length; j++)
{
    string line = lines[j];
    if (line.Contains('\r'))
    {
        string[] subLines = line.Split('\r');
        char[] mainLine = subLines[0].ToCharArray();
        for(int i=1; i<subLines.Length; i++)
        {
            string subLine = Regex.Replace(subLines[i], ".\x0008(.)", "$1");
            if (subLine.Length > mainLine.Length) mainLine = subLine.ToCharArray();
            else subLine.CopyTo(0, mainLine, 0, subLine.Length);
        }
        lines[j] = new String(mainLine);
    }
}

【讨论】:

  • \r 是唯一可能导致此行为的符号吗?那么可能会简单一点……
  • 可能不是 only 符号会导致此行为,但它是迄今为止最常见的。我已经添加了我的解决方案 - 它基本上迭代每个“真实”行并根据需要更新它
  • 别忘了\b,很常见。
  • 很好,我去看看。
  • @HansPassant:是的——我忘了​​(和^H 一样)。我已经更新了代码来处理这个问题。
猜你喜欢
  • 2019-09-10
  • 1970-01-01
  • 1970-01-01
  • 2011-03-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多