当在c#中构建Windows控制台应用程序时,是否有可能写入控制台而不必扩展当前行或去到新行?例如,如果我想显示一个百分比,表示一个流程离完成有多近,我只需要在游标所在的同一行上更新该值,而不必将每个百分比放在新行上。
这可以用“标准”c#控制台应用程序来实现吗?
当在c#中构建Windows控制台应用程序时,是否有可能写入控制台而不必扩展当前行或去到新行?例如,如果我想显示一个百分比,表示一个流程离完成有多近,我只需要在游标所在的同一行上更新该值,而不必将每个百分比放在新行上。
这可以用“标准”c#控制台应用程序来实现吗?
当前回答
您可以使用\b (backspace)转义序列来备份当前行上特定数量的字符。这只是移动当前位置,并不移除字符。
例如:
string line="";
for(int i=0; i<100; i++)
{
string backup=new string('\b',line.Length);
Console.Write(backup);
line=string.Format("{0}%",i);
Console.Write(line);
}
这里,line是写入控制台的百分比线。诀窍是为前面的输出生成正确数量的\b字符。
与\r方法相比,这种方法的优点是即使输出百分比不在行开头,if也可以工作。
其他回答
SetCursorPosition方法适用于多线程场景,而其他两个方法则不能
在行首显式地使用Carrage Return (\r),而不是(隐式或显式地)在行尾使用New line (\n),应该得到你想要的结果。例如:
void demoPercentDone() {
for(int i = 0; i < 100; i++) {
System.Console.Write( "\rProcessing {0}%...", i );
System.Threading.Thread.Sleep( 1000 );
}
System.Console.WriteLine();
}
灵感来自@E。拉湖解决方案,执行进度条用百分比。
public class ConsoleSpinner
{
private int _counter;
public void Turn(Color color, int max, string prefix = "Completed", string symbol = "■",int position = 0)
{
Console.SetCursorPosition(0, position);
Console.Write($"{prefix} {ComputeSpinner(_counter, max, symbol)}", color);
_counter = _counter == max ? 0 : _counter + 1;
}
public string ComputeSpinner(int nmb, int max, string symbol)
{
var spinner = new StringBuilder();
if (nmb == 0)
return "\r ";
spinner.Append($"[{nmb}%] [");
for (var i = 0; i < max; i++)
{
spinner.Append(i < nmb ? symbol : ".");
}
spinner.Append("]");
return spinner.ToString();
}
}
public static void Main(string[] args)
{
var progressBar= new ConsoleSpinner();
for (int i = 0; i < 1000; i++)
{
progressBar.Turn(Color.Aqua,100);
Thread.Sleep(1000);
}
}
\r用于这些场景。 \r表示回车,这意味着光标返回到行首。 这就是Windows使用\n\r作为新行标记的原因。 \n将您移动到一行,\r将您返回到行开头。
public void Update(string data)
{
Console.Write(string.Format("\r{0}", "".PadLeft(Console.CursorLeft, ' ')));
Console.Write(string.Format("\r{0}", data));
}