Estoy escribiendo una aplicación de consola c # simple que carga archivos al servidor sftp. Sin embargo, la cantidad de archivos es grande. Me gustaría mostrar el porcentaje de archivos cargados o solo el número de archivos cargados ya del número total de archivos que se cargarán.
Primero, obtengo todos los archivos y el número total de archivos.
string[] filePath = Directory.GetFiles(path, "*");
totalCount = filePath.Length;
Luego, recorro el archivo y los subo uno por uno en 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);
}
En el bucle foreach tengo una barra de progreso con la que tengo problemas. No se muestra correctamente.
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
}
La salida es solo [] 0 de 1943
¿Qué estoy haciendo mal aquí?
EDITAR:
Estoy intentando mostrar la barra de progreso mientras estoy cargando y exportando archivos XML. Sin embargo, está pasando por un bucle. Después de que termina la primera ronda, pasa a la segunda y así sucesivamente.
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++;
}
}
Nunca sale del bucle for ... ¿Alguna sugerencia?
ExportXml(xmlFilePath[i])
Respuestas:
Esta línea es tu problema:
drawTextProgressBar(0, totalCount);
Estás diciendo que el progreso es cero en cada iteración, esto debería incrementarse. Quizás use un bucle for en su lugar.
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); }
fuente
También estaba buscando una barra de progreso de la consola. No encontré uno que hiciera lo que necesitaba, así que decidí rodar el mío. Haga clic aquí para obtener el código fuente (licencia MIT).
caracteristicas:
Funciona con salida redirigida
Si redirige la salida de una aplicación de consola (por ejemplo,
Program.exe > myfile.txt
), la mayoría de las implementaciones fallarán con una excepción. Eso es porqueConsole.CursorLeft
yConsole.SetCursorPosition()
no es compatible con la salida redirigida.Implementos
IProgress<double>
Esto le permite usar la barra de progreso con operaciones asincrónicas que informan un progreso en el rango de [0..1].
A salvo de amenazas
Rápido
La
Console
clase es conocida por su pésimo desempeño. Demasiadas llamadas y su aplicación se ralentiza. Esta clase realiza solo 8 llamadas por segundo, sin importar la frecuencia con la que informe una actualización de progreso.Úselo así:
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.");
fuente
Sé que este es un hilo antiguo y me disculpo por la autopromoción, sin embargo, recientemente escribí una biblioteca de consola de código abierto disponible en nuget Goblinfactory.Konsole con soporte de barra de progreso múltiple seguro para subprocesos, que podría ayudar a cualquier persona nueva en esta página que necesite una que no bloquea el hilo principal.
Es algo diferente a las respuestas anteriores, ya que le permite iniciar las descargas y tareas en paralelo y continuar con otras tareas;
salud, espero que esto sea útil
UNA
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.");
te da este tipo de salida
El paquete nuget también incluye utilidades para escribir en una sección con ventana de la consola con soporte completo de recorte y ajuste, además de
PrintAt
varias otras clases útiles.Escribí el paquete nuget porque constantemente terminaba escribiendo muchas rutinas de consola comunes cada vez que escribía scripts y utilidades de consola de construcción y operaciones.
Si estaba descargando varios archivos, solía ir lentamente
Console.Write
a la pantalla en cada hilo y solía probar varios trucos para que la lectura de la salida intercalada en la pantalla sea más fácil de leer, por ejemplo, diferentes colores o números. Eventualmente escribí la biblioteca de ventanas para que la salida de diferentes subprocesos pudiera simplemente imprimirse en diferentes ventanas, y redujo una tonelada de código repetitivo en mis scripts de utilidad.Por ejemplo, este código,
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
produce esto
También puede crear barras de progreso dentro de una ventana tan fácilmente como escribir en las ventanas. (mezclar y combinar).
fuente
Es posible que desee probar https://www.nuget.org/packages/ShellProgressBar/
Me encontré con esta implementación de la barra de progreso: es multiplataforma, realmente fácil de usar, bastante configurable y hace lo que debería de inmediato.
Solo comparto porque me gustó mucho.
fuente
He copiado y pegado tu
ProgressBar
método. Porque su error estaba en el ciclo como se menciona en la respuesta aceptada. Pero elProgressBar
método también tiene algunos errores de sintaxis. Aquí está la versión de trabajo. Ligeramente modificado.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 }
Tenga en cuenta que @ Daniel-wolf tiene un mejor enfoque: https://stackoverflow.com/a/31193455/169714
fuente
Me gustó bastante la barra de progreso del póster original, pero descubrí que no mostraba el progreso correctamente con ciertas combinaciones de progreso / elementos totales. Lo siguiente, por ejemplo, no se dibuja correctamente, dejando un bloque gris adicional al final de la barra de progreso:
drawTextProgressBar(4114, 4114)
Rehice parte del código de dibujo para eliminar el bucle innecesario que solucionó el problema anterior y también aceleró bastante las cosas:
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 }
fuente
He creado esta práctica clase que funciona con System.Reactive. Espero que lo encuentres lo suficientemente encantador.
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(); } }
fuente
Me encontré con este hilo buscando algo más, y pensé en dejar mi código que armé y que descarga una Lista de archivos usando DownloadProgressChanged. Encuentro esto muy útil, por lo que no solo veo el progreso, sino también el tamaño real a medida que avanza el archivo. ¡Espero que ayude a alguien!
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) { }
Aquí tienes un ejemplo de la salida:
¡Espero que ayude a alguien!
fuente
Todavía soy un poco nuevo,
C#
pero creo que lo siguiente podría ayudar.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++; }
fuente