控制台应用程序中的进度条

106

我正在编写一个简单的C#控制台应用程序,用于将文件上传到SFTP服务器。然而,文件数量很大。我想要显示已上传的文件数量与待上传总文件数之比,或者仅显示已上传的文件数量。

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

string[] filePath = Directory.GetFiles(path, "*");
totalCount = filePath.Length;

然后我使用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);
}
在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
}

输出只是[ ] 0/1943

我在这里做错了什么?

编辑:

我试图在加载和导出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++;
     }
 }

它从未离开for循环...有任何建议吗?


xmlCount和count是什么? - eddie_cat
1
另外,为什么for循环在foreach循环内部?它似乎正在迭代相同的内容。保留foreach循环可能是不必要的。 - eddie_cat
xmlFilePath.Length给了我相同的输出。代码没有出错。目前文件夹中有1493个XML文件。一旦达到1493,i就会重新从0开始。 - smr5
1
你移除了外层的foreach循环吗?然后将注释掉的部分改为ExportXml(xmlFilePath[i]) - eddie_cat
1
就是这样。我只有一个for循环,它可以工作。 - smr5
显示剩余2条评论
11个回答

0

根据以上所有帖子,我做了一个改进版。

  1. 没有跳动的光标,现在已经看不见了。

  2. 性能得到了提升(原来的1/5~1/10的时间成本)。

  3. 基于接口的设计,易于移植到其他项目中。

     public class ConsoleProgressBar : IProgressBar
     {
         private const ConsoleColor ForeColor = ConsoleColor.Green;
         private const ConsoleColor BkColor = ConsoleColor.Gray;
         private const int DefaultWidthOfBar = 32;
         private const int TextMarginLeft = 3;
    
         private readonly int _total;
         private readonly int _widthOfBar;
    
         public ConsoleProgressBar(int total, int widthOfBar = DefaultWidthOfBar)
         {
             _total = total;
             _widthOfBar = widthOfBar;
         }
    
         private bool _intited;
         public void Init()
         {
             _lastPosition = 0;
    
             //绘制空进度条
             Console.CursorVisible = false;
             Console.CursorLeft = 0;
             Console.Write("["); //开始
             Console.CursorLeft = _widthOfBar;
             Console.Write("]"); //结束
             Console.CursorLeft = 1;
    
             //绘制背景进度条
             for (var position = 1; position < _widthOfBar; position++) //跳过第一个位置"["
             {
                 Console.BackgroundColor = BkColor;
                 Console.CursorLeft = position;
                 Console.Write(" ");
             }
         }
    
         public void ShowProgress(int currentCount)
         {
             if (!_intited)
             {
                 Init();
                 _intited = true;
             }
             DrawTextProgressBar(currentCount);
         }
    
         private int _lastPosition;
    
         public void DrawTextProgressBar(int currentCount)
         {
             //绘制当前进度块
             var position = currentCount * _widthOfBar / _total;
             if (position != _lastPosition)
             {
                 _lastPosition = position;
                 Console.BackgroundColor = ForeColor;
                 Console.CursorLeft = position >= _widthOfBar ? _widthOfBar - 1 : position;
                 Console.Write(" ");
             }
    
             //绘制总数
             Console.CursorLeft = _widthOfBar + TextMarginLeft;
             Console.BackgroundColor = ConsoleColor.Black;
             Console.Write(currentCount + " of " + _total + "    "); //末尾的空格去除任何多余的内容
         }
     }
    
     public interface IProgressBar
     {
         public void ShowProgress(int currentCount);
     }
    

以下是一些测试代码:

        var total = 100;
        IProgressBar progressBar = new ConsoleProgressBar(total);
        for (var i = 0; i <= total; i++)
        {
            progressBar.ShowProgress(i);
            Thread.Sleep(50);
        }

        Thread.Sleep(500);
        Console.Clear();

        total = 9999;
        progressBar = new ConsoleProgressBar(total);
        for (var i = 0; i <= total; i++)
        {
            progressBar.ShowProgress(i);
        }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接