Ich schreibe eine einfache C # -Konsolen-App, die Dateien auf den SFTP-Server hochlädt. Die Anzahl der Dateien ist jedoch groß. Ich möchte entweder den Prozentsatz der hochgeladenen Dateien oder nur die Anzahl der bereits hochgeladenen Dateien aus der Gesamtzahl der hochzuladenden Dateien anzeigen.
Zuerst bekomme ich alle Dateien und die Gesamtzahl der Dateien.
string[] filePath = Directory.GetFiles(path, "*");
totalCount = filePath.Length;
Dann durchlaufe ich die Datei und lade sie einzeln in jeder Schleife hoch.
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);
}
In der foreach-Schleife habe ich einen Fortschrittsbalken, mit dem ich Probleme habe. Es wird nicht richtig angezeigt.
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
}
Die Ausgabe ist nur [] 0 von 1943
Was mache ich hier falsch?
BEARBEITEN:
Ich versuche, den Fortschrittsbalken anzuzeigen, während ich XML-Dateien lade und exportiere. Es geht jedoch durch eine Schleife. Nachdem es die erste Runde beendet hat, geht es zur zweiten und so weiter.
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++;
}
}
Es verlässt nie die for-Schleife ... Irgendwelche Vorschläge?
ExportXml(xmlFilePath[i])
Antworten:
Diese Zeile ist Ihr Problem:
drawTextProgressBar(0, totalCount);
Sie sagen, der Fortschritt ist in jeder Iteration Null, dies sollte erhöht werden. Verwenden Sie stattdessen möglicherweise eine for-Schleife.
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); }
quelle
Ich suchte auch nach einer Konsolen-Fortschrittsanzeige. Ich habe keinen gefunden, der das tat, was ich brauchte, also habe ich beschlossen, meinen eigenen zu rollen. Klicken Sie hier für den Quellcode (MIT-Lizenz).
Eigenschaften:
Funktioniert mit umgeleiteten Ausgaben
Wenn Sie die Ausgabe einer Konsolenanwendung umleiten (z. B.
Program.exe > myfile.txt
), stürzen die meisten Implementierungen mit einer Ausnahme ab. Das liegt daran ,Console.CursorLeft
undConsole.SetCursorPosition()
unterstützt nicht umgeleiteter Ausgabe.Geräte
IProgress<double>
Auf diese Weise können Sie den Fortschrittsbalken mit asynchronen Vorgängen verwenden, die einen Fortschritt im Bereich von [0..1] melden.
Gewindesicher
Schnell
Die
Console
Klasse ist bekannt für ihre miserable Leistung. Zu viele Anrufe, und Ihre Anwendung wird langsamer. Diese Klasse führt nur 8 Aufrufe pro Sekunde aus, unabhängig davon, wie oft Sie eine Fortschrittsaktualisierung melden.Verwenden Sie es so:
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.");
quelle
Ich weiß, dass dies ein alter Thread ist, und entschuldige mich für die Eigenwerbung. Ich habe jedoch kürzlich eine Open-Source-Konsolenbibliothek geschrieben, die auf nuget Goblinfactory.Konsole verfügbar ist und threadsichere Unterstützung für mehrere Fortschrittsbalken bietet blockiert nicht den Haupt-Thread.
Es unterscheidet sich etwas von den obigen Antworten, da Sie die Downloads und Aufgaben parallel starten und mit anderen Aufgaben fortfahren können.
Prost, hoffe das ist hilfreich
EIN
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.");
gibt Ihnen diese Art der Ausgabe
Das Nuget-Paket enthält auch Dienstprogramme zum Schreiben in einen Fensterbereich der Konsole mit vollständiger Unterstützung für das Beschneiden und Umschließen
PrintAt
sowie verschiedene andere hilfreiche Klassen.Ich habe das Nuget-Paket geschrieben, weil ich ständig viele gängige Konsolenroutinen geschrieben habe, wenn ich Build- und Ops-Konsolenskripte und -Dienstprogramme geschrieben habe.
Wenn ich mehrere Dateien heruntergeladen habe, habe ich in
Console.Write
jedem Thread langsam zum Bildschirm gewechselt und verschiedene Tricks ausprobiert, um das Lesen der verschachtelten Ausgabe auf dem Bildschirm einfacher zu machen, z. B. verschiedene Farben oder Zahlen. Ich habe schließlich die Fensterbibliothek geschrieben, damit die Ausgabe von verschiedenen Threads einfach in verschiedene Fenster gedruckt werden kann, und sie hat eine Menge Code in meinen Dienstprogramm-Skripten reduziert.Zum Beispiel dieser Code,
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
produziert dies
Sie können Fortschrittsbalken in einem Fenster genauso einfach erstellen wie in die Fenster schreiben. (mischen und Anpassen).
quelle
Vielleicht möchten Sie https://www.nuget.org/packages/ShellProgressBar/ ausprobieren.
Ich bin gerade auf diese Implementierung des Fortschrittsbalkens gestoßen - die plattformübergreifende, sehr benutzerfreundliche, konfigurierbare und sofort einsatzbereite Funktion.
Nur teilen, weil es mir sehr gut gefallen hat.
quelle
Ich habe Ihre
ProgressBar
Methode kopiert . Weil Ihr Fehler als akzeptierte Antwort in der Schleife war. DieProgressBar
Methode weist jedoch auch einige Syntaxfehler auf. Hier ist die Arbeitsversion. Leicht modifiziert.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 }
Bitte beachten Sie, dass @ Daniel-wolf einen besseren Ansatz hat: https://stackoverflow.com/a/31193455/169714
quelle
Ich habe diese praktische Klasse erstellt, die mit System.Reactive funktioniert. Ich hoffe du findest es schön genug.
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(); } }
quelle
Ich mochte den Fortschrittsbalken des Originalplakats sehr, stellte jedoch fest, dass der Fortschritt bei bestimmten Kombinationen aus Fortschritt und Gesamtelement nicht korrekt angezeigt wurde. Folgendes wird beispielsweise nicht korrekt gezeichnet, sodass am Ende des Fortschrittsbalkens ein zusätzlicher grauer Block verbleibt:
drawTextProgressBar(4114, 4114)
Ich habe einen Teil des Zeichnungscodes erneut ausgeführt, um die unnötige Schleife zu entfernen, die das oben genannte Problem behoben und die Dinge erheblich beschleunigt hat:
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 }
quelle
Ich bin gerade auf diesen Thread gestoßen, als ich nach etwas anderem gesucht habe, und dachte, ich würde meinen Code, den ich zusammengestellt habe und der eine Liste von Dateien mit DownloadProgressChanged herunterlädt, ablegen. Ich finde das super hilfreich, damit ich nicht nur den Fortschritt sehe, sondern auch die tatsächliche Größe, während die Datei durchkommt. Hoffe es hilft jemandem!
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) { }
Hier ist ein Beispiel für die Ausgabe:
Hoffe es hilft jemandem!
quelle
Ich bin noch ein bisschen neu in,
C#
aber ich glaube, dass das Folgende helfen könnte.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++; }
quelle