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)
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 上)
\nclass 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}\nRun Code Online (Sandbox Code Playgroud)\n\n
我有复制粘贴你的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
我非常喜欢原始海报的进度条,但发现它没有正确显示某些进度/总项目组合的进度。例如,以下内容无法正确绘制,在进度条的末尾留下一个额外的灰色块:
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)
我创建了这个与 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)
您可能要尝试https://www.nuget.org/packages/ShellProgressBar/
我只是偶然发现了这个进度条的实现-它的跨平台,非常易于使用,可配置且可以立即完成。
只是分享,因为我非常喜欢它。