当在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也可以工作。

其他回答

我在vb.net上寻找同样的解决方案,我发现了这个,它很棒。

然而,@JohnOdom建议了一个更好的方法来处理空格,如果前一个空格比当前空格大。

我在vb.net做了一个函数,认为有人可以得到帮助。

这是我的代码:

Private Sub sPrintStatus(strTextToPrint As String, Optional boolIsNewLine As Boolean = False)
    REM intLastLength is declared as public variable on global scope like below
    REM intLastLength As Integer
    If boolIsNewLine = True Then
        intLastLength = 0
    End If
    If intLastLength > strTextToPrint.Length Then
        Console.Write(Convert.ToChar(13) & strTextToPrint.PadRight(strTextToPrint.Length + (intLastLength - strTextToPrint.Length), Convert.ToChar(" ")))
    Else
        Console.Write(Convert.ToChar(13) & strTextToPrint)
    End If
    intLastLength = strTextToPrint.Length
End Sub

你可以使用控制台。SetCursorPosition设置光标的位置,然后在当前位置写入。

下面是一个简单的“spinner”的例子:

static void Main(string[] args)
{
    var spin = new ConsoleSpinner();
    Console.Write("Working....");
    while (true) 
    {
        spin.Turn();
    }
}

public class ConsoleSpinner
{
    int counter;

    public void Turn()
    {
        counter++;        
        switch (counter % 4)
        {
            case 0: Console.Write("/"); counter = 0; break;
            case 1: Console.Write("-"); break;
            case 2: Console.Write("\\"); break;
            case 3: Console.Write("|"); break;
        }
        Thread.Sleep(100);
        Console.SetCursorPosition(Console.CursorLeft - 1, Console.CursorTop);
    }
}

请注意,您必须确保用新的输出或空白覆盖任何现有输出。

更新:因为它被批评的例子移动光标只向后一个字符,我将添加这个澄清:使用SetCursorPosition你可以设置光标到控制台窗口的任何位置。

Console.SetCursorPosition(0, Console.CursorTop);

将光标设置到当前行的开头(或者您可以使用Console。CursorLeft = 0直接)。

您可以使用\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也可以工作。

这是另一个选项:D

class Program
{
    static void Main(string[] args)
    {
        Console.Write("Working... ");
        int spinIndex = 0;
        while (true)
        {
            // obfuscate FTW! Let's hope overflow is disabled or testers are impatient
            Console.Write("\b" + @"/-\|"[(spinIndex++) & 3]);
        }
    }
}

如果你只打印“\r”到控制台,光标会回到当前行的开头,然后你可以重写它。这应该可以达到目的:

for(int i = 0; i < 100; ++i)
{
    Console.Write("\r{0}%   ", i);
}

注意数字后面的几个空格,以确保之前的任何内容都被擦除。 还要注意使用Write()而不是WriteLine(),因为您不想在行末添加“\n”。