控制台应用程序中的进度条
我正在写一个简单的c#控制台应用程序,将file upload到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 }
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++; } }
它永远不会离开for循环…任何build议?
这条线是你的问题:
drawTextProgressBar(0, totalCount);
你说的每个迭代的进度都是零,这应该是递增的。 也许使用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); }
我也在寻找一个控制台进度条。 我没有find我所需要的,所以我决定推出自己的产品。 点击这里查看源代码 (MIT许可证)。
特征:
-
与redirect的输出一起使用
如果您redirect控制台应用程序的输出(例如,
Program.exe > myfile.txt
),大多数实现将会崩溃,并出现exception。 这是因为Console.CursorLeft
和Console.SetCursorPosition()
不支持redirect的输出。 -
实现
IProgress<double>
这使您可以使用进度条进行asynchronous操作,报告[0..1]范围内的进度。
-
线程安全
-
快速
Console
类的恶劣performance是臭名昭着的。 太多的电话,并且你的应用程序变慢。 无论您多久报告一次进度更新,该类每秒只能执行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.");
我有复制粘贴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 }
请注意,@丹尼尔狼有一个更好的办法: https : //stackoverflow.com/a/31193455/169714
我知道这是一个古老的线程,并为自我推销道歉,但是我最近编写了一个开源的控制台库上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.");
给你这种types的输出
Nuget软件包还包括用于写入到控制台的窗口部分的实用程序,具有完整的剪切和包装支持,以及PrintAt
和各种其他有用的类。
我写了nuget包,因为每当我编写构build和操作控制台脚本和实用程序时,我总是会写很多常见的控制台例程。
如果我正在下载几个文件,我就会慢慢地将Console.Write
每个线程的屏幕上,并用来尝试各种技巧,使屏幕上的交错输出更容易阅读,例如不同的颜色或数字。 我最终编写了窗口库,以便不同线程的输出可以简单地打印到不同的窗口,并在我的实用程序脚本中减less了大量的样板代码。
例如,这个代码,
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
产生这个
您也可以在窗口内创build进度条,就像写入窗口一样容易。 (连连看)。
我非常喜欢原始海报的进度条,但是发现在某些进度/总项目组合下它没有正确显示进度。 例如,以下内容不能正确绘制,在进度条的末尾留下额外的灰色块:
drawTextProgressBar(4114, 4114)
我重新做了一些绘图代码,以消除不必要的循环固定上述问题,也加快了一些:
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 }
我只是偶然发现了这个线程寻找其他的东西,我想我会放下我的代码,我把它放在一起,使用DownloadProgressChanged下载一个文件列表。 我觉得这个超级有用,所以我不仅看到了进展,而且还看到了文件的实际大小。 希望它可以帮助别人!
public static bool DownloadFile(List<string> files, string host, string username, string password, string savePath) { try { //setup FTP client foreach (string f in files) { FILENAME = f.Split('\\').Last(); wc.DownloadFileCompleted += new AsyncCompletedEventHandler(Completed); wc.DownloadProgressChanged += new DownloadProgressChangedEventHandler(ProgressChanged); wc.DownloadFileAsync(new Uri(host + f), savePath + f); while (wc.IsBusy) System.Threading.Thread.Sleep(1000); Console.Write(" COMPLETED!"); Console.WriteLine(); } } catch (Exception ex) { Console.WriteLine(ex.ToString()); return false; } return true; } private static void ProgressChanged(object obj, System.Net.DownloadProgressChangedEventArgs e) { Console.Write("\r --> Downloading " + FILENAME +": " + string.Format("{0:n0}", e.BytesReceived / 1000) + " kb"); } private static void Completed(object obj, AsyncCompletedEventArgs e) { }
这是一个输出的例子:
希望它可以帮助别人!
我对C#
还是一个新的东西,但我相信下面可能会有所帮助。
string[] xmlFilePath = Directory.GetFiles(xmlFullpath, "*.xml"); Console.WriteLine("Loading XML files..."); int count = 0; foreach (string file in xmlFilePath) { //ExportXml(file, styleSheet); drawTextProgressBar(count, xmlCount); count++; }