当在c#中构建Windows控制台应用程序时,是否有可能写入控制台而不必扩展当前行或去到新行?例如,如果我想显示一个百分比,表示一个流程离完成有多近,我只需要在游标所在的同一行上更新该值,而不必将每个百分比放在新行上。

这可以用“标准”c#控制台应用程序来实现吗?


当前回答

以下是我对s soosh和0xA3的回答的看法。 它可以在更新旋转器的同时用用户消息更新控制台,并且还有一个运行时间指示器。

public class ConsoleSpiner : IDisposable
{
    private static readonly string INDICATOR = "/-\\|";
    private static readonly string MASK = "\r{0} {1:c} {2}";
    int counter;
    Timer timer;
    string message;

    public ConsoleSpiner() {
        counter = 0;
        timer = new Timer(200);
        timer.Elapsed += TimerTick;
    }

    public void Start() {
        timer.Start();
    }

    public void Stop() {
        timer.Stop();
        counter = 0;
    }

    public string Message {
        get { return message; }
        set { message = value; }
    }

    private void TimerTick(object sender, ElapsedEventArgs e) {
        Turn();
    }

    private void Turn() {
        counter++;
        var elapsed = TimeSpan.FromMilliseconds(counter * 200);
        Console.Write(MASK, INDICATOR[counter % 4], elapsed, this.Message);
    }

    public void Dispose() {
        Stop();
        timer.Elapsed -= TimerTick;
        this.timer.Dispose();
    }
}

用法是这样的:

class Program
{
    static void Main(string[] args)
    {
        using (var spinner = new ConsoleSpiner())
        {
            spinner.Start();
            spinner.Message = "About to do some heavy staff :-)"
            DoWork();
            spinner.Message = "Now processing other staff".
            OtherWork();
            spinner.Stop();
        }
        Console.WriteLine("COMPLETED!!!!!\nPress any key to exit.");

    }
}

其他回答

来自MSDN的控制台文档:

您可以通过设置 TextWriter。属性的NewLine 属性转移到另一行 终止的字符串。例如, c#语句,Console.Error.NewLine = “\r\n\r\n”;,设置行终止 字符串用于标准错误输出 流到两车厢返回并行 饲料序列。然后你就可以 显式调用WriteLine方法 错误输出流对象的 在c#语句中, Console.Error.WriteLine ();

所以,我这样做了:

Console.Out.Newline = String.Empty;

然后我就可以自己控制输出了;

Console.WriteLine("Starting item 1:");
    Item1();
Console.WriteLine("OK.\nStarting Item2:");

另一种方法。

如果你想让生成的文件看起来很酷,这是可行的。

                int num = 1;
                var spin = new ConsoleSpinner();
                Console.ForegroundColor = ConsoleColor.Green;
                Console.Write("");
                while (true)
                {
                    spin.Turn();
                    Console.Write("\r{0} Generating Files ", num);
                    num++;
                }

这是我从下面的一些答案得到的方法,并修改了它

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;
                case 4: Console.Write("\r"); break;
            }
            Thread.Sleep(100);
            Console.SetCursorPosition(23, Console.CursorTop);
        }
    }

SetCursorPosition方法适用于多线程场景,而其他两个方法则不能

您可以使用\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]);
        }
    }
}