控制台应用程序的进度条

smr*_*mr5 68 c# console progress

我正在写一个简单的c#控制台应用程序,它将文件上传到sftp服务器.但是,文件量很大.我想显示已上传文件的百分比,或者只显示已上传文件的数量,以及要上传的文件总数.

首先,我获取所有文件和文件总数.

string[] filePath = Directory.GetFiles(path, "*");
totalCount = filePath.Length;
Run Code Online (Sandbox Code Playgroud)

然后我遍历文件并在foreach循环中逐个上传它们.

foreach(string file in filePath)
{
    string FileName = Path.GetFileName(file);
    //copy the files
    oSftp.Put(LocalDirectory + "/" + FileName, _ftpDirectory + "/" + FileName);
    //Console.WriteLine("Uploading file..." + FileName);
    drawTextProgressBar(0, totalCount);
}
Run Code Online (Sandbox Code Playgroud)

在foreach循环中,我有一个进度条,我遇到了问题.它无法正常显示.

private static void drawTextProgressBar(int progress, int total)
{
    //draw empty progress bar
    Console.CursorLeft = 0;
    Console.Write("["); //start
    Console.CursorLeft = 32;
    Console.Write("]"); //end
    Console.CursorLeft = 1;
    float onechunk = 30.0f / total;

    //draw filled part
    int position = 1;
    for (int i = 0; i < onechunk * progress; i++)
    {
        Console.BackgroundColor = ConsoleColor.Gray;
        Console.CursorLeft = position++;
        Console.Write(" ");
    }

    //draw unfilled part
    for (int i = position; i <= 31 ; i++)
    {
        Console.BackgroundColor = ConsoleColor.Green;
        Console.CursorLeft = position++;
        Console.Write(" ");
    }

    //draw totals
    Console.CursorLeft = 35;
    Console.BackgroundColor = ConsoleColor.Black;
    Console.Write(progress.ToString() + " of " + total.ToString() + "    "); //blanks at the end remove any excess
}
Run Code Online (Sandbox Code Playgroud)

1943年的输出仅为[] 0

我在这做错了什么?

编辑:

我正在尝试在加载和导出XML文件时显示进度条.然而,它正在经历一个循环.完成第一轮后,它会进入第二轮,依此类推.

string[] xmlFilePath = Directory.GetFiles(xmlFullpath, "*.xml");
Console.WriteLine("Loading XML files...");
foreach (string file in xmlFilePath)
{
     for (int i = 0; i < xmlFilePath.Length; i++)
     {
          //ExportXml(file, styleSheet);
          drawTextProgressBar(i, xmlCount);
          count++;
     }
 }
Run Code Online (Sandbox Code Playgroud)

它永远不会离开for循环......有什么建议吗?

Dan*_*olf 165

我也在寻找一个控制台进度条.我没有找到一个能做我需要的东西,所以我决定自己动手.单击此处获取源代码(MIT许可证).

动画进度条

特征:

  • 使用重定向输出

    如果重定向控制台应用程序的输出(例如,Program.exe > myfile.txt),大多数实现将崩溃并出现异常.那是因为Console.CursorLeft并且Console.SetCursorPosition()不支持重定向输出.

  • 器物 IProgress<double>

    这允许您使用进度条和异步操作来报告[0..1]范围内的进度.

  • 线程安全

  • 快速

    Console班以其糟糕的表现而臭名昭着.对它的调用太多,您的应用程序运行速度变慢.无论您报告进度更新的频率如何,此类每秒仅执行8次调用.

像这样使用它:

Console.Write("Performing some task... ");
using (var progress = new ProgressBar()) {
    for (int i = 0; i <= 100; i++) {
        progress.Report((double) i / 100);
        Thread.Sleep(20);
    }
}
Console.WriteLine("Done.");
Run Code Online (Sandbox Code Playgroud)

  • 这个gif很有吸引力. (6认同)
  • 这看起来很整洁!您是否考虑向其添加诸如MIT之类的OSS许可证?http://choosealicense.com/ (2认同)
  • 好主意。做到了。 (2认同)

sno*_*ode 13

我知道这是一个旧的线程,并为自我推销道歉,但是我最近在nuget Goblinfactory.Konsole上编写了一个开源控制台库,其中 包含线程安全的多个进度条支持,这可能有助于任何新页面需要一个不阻止主线程.

它与上面的答案有些不同,因为它允许您并行启动下载和任务并继续执行其他任务;

欢呼,希望这是有帮助的

一个

var t1 = Task.Run(()=> {
   var p = new ProgressBar("downloading music",10);
   ... do stuff
});

var t2 = Task.Run(()=> {
   var p = new ProgressBar("downloading video",10);
   ... do stuff
});

var t3 = Task.Run(()=> {
   var p = new ProgressBar("starting server",10);
   ... do stuff .. calling p.Refresh(n);
});

Task.WaitAll(new [] { t1,t2,t3 }, 20000);
Console.WriteLine("all done.");
Run Code Online (Sandbox Code Playgroud)

为您提供此类输出

在此输入图像描述

nuget包还包括用于写入控制台窗口部分的实用程序,具有完全剪切和包装支持,以及PrintAt各种其他有用的类.

我编写了nuget包,因为每当我编写build和ops控制台脚本和实用程序时,我总是会编写很多常见的控制台例程.

如果我正在下载几个文件,我曾经慢慢Console.Write地在每个线程的屏幕上,并习惯尝试各种技巧,使阅读屏幕上的交错输出更容易阅读,例如不同的颜色或数字.我最终编写了窗口库,以便不同线程的输出可以简单地打印到不同的窗口,并在我的实用程序脚本中减少了大量的样板代码.

例如,这段代码,

        var con = new Window(200,50);
        con.WriteLine("starting client server demo");
        var client = new Window(1, 4, 20, 20, ConsoleColor.Gray, ConsoleColor.DarkBlue, con);
        var server = new Window(25, 4, 20, 20, con);
        client.WriteLine("CLIENT");
        client.WriteLine("------");
        server.WriteLine("SERVER");
        server.WriteLine("------");
        client.WriteLine("<-- PUT some long text to show wrapping");
        server.WriteLine(ConsoleColor.DarkYellow, "--> PUT some long text to show wrapping");
        server.WriteLine(ConsoleColor.Red, "<-- 404|Not Found|some long text to show wrapping|");
        client.WriteLine(ConsoleColor.Red, "--> 404|Not Found|some long text to show wrapping|");

        con.WriteLine("starting names demo");
        // let's open a window with a box around it by using Window.Open
        var names = Window.Open(50, 4, 40, 10, "names");
        TestData.MakeNames(40).OrderByDescending(n => n).ToList()
             .ForEach(n => names.WriteLine(n));

        con.WriteLine("starting numbers demo");
        var numbers = Window.Open(50, 15, 40, 10, "numbers", 
              LineThickNess.Double,ConsoleColor.White,ConsoleColor.Blue);
        Enumerable.Range(1,200).ToList()
             .ForEach(i => numbers.WriteLine(i.ToString())); // shows scrolling
Run Code Online (Sandbox Code Playgroud)

产生这个

在此输入图像描述

您还可以在窗口内创建进度条,就像写入窗口一样容易.(连连看).


edd*_*cat 10

这行是你的问题:

drawTextProgressBar(0, totalCount);
Run Code Online (Sandbox Code Playgroud)

你说每次迭代的进度都是零,这应该增加.也许使用for循环代替.

for (int i = 0; i < filePath.length; i++)
{
    string FileName = Path.GetFileName(filePath[i]);
    //copy the files
    oSftp.Put(LocalDirectory + "/" + FileName, _ftpDirectory + "/" + FileName);
    //Console.WriteLine("Uploading file..." + FileName);
    drawTextProgressBar(i, totalCount);
}
Run Code Online (Sandbox Code Playgroud)


小智 8

C# 中的控制台进度栏(完整代码 - 只需复制并粘贴到您的 IDE 上)

\n
class ConsoleUtility\n{\n    const char _block = \'\xe2\x96\xa0\';\n    const string _back = "\\b\\b\\b\\b\\b\\b\\b\\b\\b\\b\\b\\b\\b\\b\\b\\b\\b";\n    const string _twirl = "-\\\\|/";\n\n    public static void WriteProgressBar(int percent, bool update = false)\n    {\n        if (update)\n            Console.Write(_back);\n        Console.Write("[");\n        var p = (int)((percent / 10f) + .5f);\n        for (var i = 0; i < 10; ++i)\n        {\n            if (i >= p)\n                Console.Write(\' \');\n            else\n                Console.Write(_block);\n        }\n        Console.Write("] {0,3:##0}%", percent);\n    }\n\n    public static void WriteProgress(int progress, bool update = false)\n    {\n        if (update)\n            Console.Write("\\b");\n        Console.Write(_twirl[progress % _twirl.Length]);\n    }\n}\n\n\n//This is how to call in your main method\nstatic void Main(string[] args)\n{\n    ConsoleUtility.WriteProgressBar(0);\n    for (var i = 0; i <= 100; ++i)\n    {\n       ConsoleUtility.WriteProgressBar(i, true);\n       Thread.Sleep(50);\n    }\n\n    Console.WriteLine();\n    ConsoleUtility.WriteProgress(0);\n    for (var i = 0; i <= 100; ++i)\n    {\n        ConsoleUtility.WriteProgress(i, true);\n        Thread.Sleep(50);\n    }\n}\n
Run Code Online (Sandbox Code Playgroud)\n

输出:C# 进度条

\n


JP *_*ons 6

我有复制粘贴你的ProgressBar方法.因为您的错误是在接受的答案中提到的循环中.但该ProgressBar方法也存在一些语法错误.这是工作版本.略有修改.

private static void ProgressBar(int progress, int tot)
{
    //draw empty progress bar
    Console.CursorLeft = 0;
    Console.Write("["); //start
    Console.CursorLeft = 32;
    Console.Write("]"); //end
    Console.CursorLeft = 1;
    float onechunk = 30.0f / tot;

    //draw filled part
    int position = 1;
    for (int i = 0; i < onechunk * progress; i++)
    {
        Console.BackgroundColor = ConsoleColor.Green;
        Console.CursorLeft = position++;
        Console.Write(" ");
    }

    //draw unfilled part
    for (int i = position; i <= 31; i++)
    {
        Console.BackgroundColor = ConsoleColor.Gray;
        Console.CursorLeft = position++;
        Console.Write(" ");
    }

    //draw totals
    Console.CursorLeft = 35;
    Console.BackgroundColor = ConsoleColor.Black;
    Console.Write(progress.ToString() + " of " + tot.ToString() + "    "); //blanks at the end remove any excess
}
Run Code Online (Sandbox Code Playgroud)

请注意@ Daniel-wolf有更好的方法:https://stackoverflow.com/a/31193455/169714


Nic*_*o M 6

我非常喜欢原始海报的进度条,但发现它没有正确显示某些进度/总项目组合的进度。例如,以下内容无法正确绘制,在进度条的末尾留下一个额外的灰色块:

drawTextProgressBar(4114, 4114)
Run Code Online (Sandbox Code Playgroud)

我重新编写了一些绘图代码以删除不必要的循环,从而解决了上述问题,并大大加快了速度:

public static void drawTextProgressBar(string stepDescription, int progress, int total)
{
    int totalChunks = 30;

    //draw empty progress bar
    Console.CursorLeft = 0;
    Console.Write("["); //start
    Console.CursorLeft = totalChunks + 1;
    Console.Write("]"); //end
    Console.CursorLeft = 1;

    double pctComplete = Convert.ToDouble(progress) / total;
    int numChunksComplete = Convert.ToInt16(totalChunks * pctComplete);

    //draw completed chunks
    Console.BackgroundColor = ConsoleColor.Green;
    Console.Write("".PadRight(numChunksComplete));

    //draw incomplete chunks
    Console.BackgroundColor = ConsoleColor.Gray;
    Console.Write("".PadRight(totalChunks - numChunksComplete));

    //draw totals
    Console.CursorLeft = totalChunks + 5;
    Console.BackgroundColor = ConsoleColor.Black;

    string output = progress.ToString() + " of " + total.ToString();
    Console.Write(output.PadRight(15) + stepDescription); //pad the output so when changing from 3 to 4 digits we avoid text shifting
}
Run Code Online (Sandbox Code Playgroud)


Sup*_*JMN 6

我创建了这个与 System.Reactive 一起使用的方便的类。我希望你觉得它足够可爱。

public class ConsoleDisplayUpdater : IDisposable
{
    private readonly IDisposable progressUpdater;

    public ConsoleDisplayUpdater(IObservable<double> progress)
    {
        progressUpdater = progress.Subscribe(DisplayProgress);
    }

    public int Width { get; set; } = 50;

    private void DisplayProgress(double progress)
    {
        if (double.IsNaN(progress))
        {
            return;
        }

        var progressBarLenght = progress * Width;
        System.Console.CursorLeft = 0;
        System.Console.Write("[");
        var bar = new string(Enumerable.Range(1, (int) progressBarLenght).Select(_ => '=').ToArray());

        System.Console.Write(bar);

        var label = $@"{progress:P0}";
        System.Console.CursorLeft = (Width -label.Length) / 2;
        System.Console.Write(label);
        System.Console.CursorLeft = Width;
        System.Console.Write("]");
    }

    public void Dispose()
    {
        progressUpdater?.Dispose();
    }
}
Run Code Online (Sandbox Code Playgroud)


Sch*_*der 5

您可能要尝试https://www.nuget.org/packages/ShellProgressBar/

我只是偶然发现了这个进度条的实现-它的跨平台,非常易于使用,可配置且可以立即完成。

只是分享,因为我非常喜欢它。