2009-05-12 21 views
87

Tengo un programa Java ejecutándose en modo de línea de comando. Me gustaría mostrar una barra de progreso, que muestra el porcentaje de trabajo realizado. El mismo tipo de barra de progreso que vería usando wget bajo Unix. ¿Esto es posible?Barra de progreso de la línea de comando en Java

+0

no sé la respuesta a su pregunta específica, pero se puede empezar por el control de las bibliotecas mencionadas en esta pregunta : http://stackoverflow.com/questions/435740/are-there-good-java-libraries-that-facilitate-building-command-line-applications – Jonik

+0

Gracias. Las bibliotecas citadas allí son más sobre el análisis de argumentos de línea de comandos, en lugar de mostrarse en la consola. Pero gracias de todos modos. –

+6

Esto está en el tema. OP pregunta si es posible, no para una recomendación de la biblioteca (al menos en la edición actual) –

Respuesta

132

He implementado este tipo de cosas antes. No se trata tanto de java, sino de qué personajes enviar a la consola.

La clave es la diferencia entre \n y \r. \n va al inicio de una nueva línea. Pero \r es solo retorno de carro - vuelve al inicio de la misma línea.

Así que lo que hay que hacer es imprimir la barra de progreso, por ejemplo, mediante la impresión de la cadena

"|========  |\r" 

En el siguiente pulso de la barra de progreso, sobrescribir la misma línea con una barra más larga. (Porque estamos usando \ r, que permanecer en la misma línea) Por ejemplo:

"|=========  |\r" 

Lo que hay que recordar que hacer, es cuando se hace, si a continuación, sólo imprime

"done!\n" 

Usted todavía puede tener algo de basura de la barra de progreso en la línea. Entonces, cuando haya terminado con la barra de progreso, asegúrese de imprimir suficiente espacio en blanco para eliminarla de la línea. Por ejemplo:

"done    |\n" 

Espero que ayude.

+0

Claro ayuda. Muchas gracias. –

+0

¿Es esto realmente multiplataforma? Probablemente se comportará bien en Windows y Linux, pero ¿qué hay de los Mac? No tengo uno, así que no puedo probarlo ... –

+1

@RaduMurzea OS X es un sistema operativo * NIX, así que si funciona en Linux, funcionará en OS X (eso no es cierto para todo, pero eso es cierto aquí). – bfontaine

2

Esto sería posible con una biblioteca Java Curses. This es lo que he encontrado. No lo he usado yo mismo y no sé si es multiplataforma.

+0

Las maldiciones pueden ser un poco sobrecargadas para el uso fácil que necesito, pero eso seguro es una pista. Gracias. –

5

C# Ejemplo pero asumo que esto es lo mismo para System.out.print en Java. No dude en corregirme si me equivoco.

Básicamente, desea escribir el carácter de escape \r al comienzo de su mensaje que hará que el cursor regrese al inicio de la línea (Line Feed) sin moverse a la siguiente línea.

static string DisplayBar(int i) 
    { 
     StringBuilder sb = new StringBuilder(); 

     int x = i/2; 
     sb.Append("|"); 
     for (int k = 0; k < 50; k++) 
      sb.AppendFormat("{0}", ((x <= k) ? " " : "=")); 
     sb.Append("|"); 

     return sb.ToString(); 
    } 

    static void Main(string[] args) 
    { 
     for (int i = 0; i <= 100; i++) 
     { 
      System.Threading.Thread.Sleep(200); 
      Console.Write("\r{0} {1}% Done", DisplayBar(i), i); 
     } 

     Console.ReadLine(); 

    } 
+0

Buen ejemplo, seguro que será útil. Gracias. –

+0

¡Hermoso! Gracias. Funciona como un encantador. Fácil de leer. Lovely –

17

He encontrado el siguiente código para que funcione correctamente. Escribe bytes en el búfer de salida. Quizás los métodos que utilizan un escritor como el método System.out.println() reemplazan las ocurrencias de \r a \n para que coincida con la terminación de línea nativa del objetivo (si no está configurado correctamente).

public class Main{ 
    public static void main(String[] arg) throws Exception { 
     String anim= "|/-\\"; 
     for (int x =0 ; x < 100 ; x++) { 
      String data = "\r" + anim.charAt(x % anim.length()) + " " + x; 
      System.out.write(data.getBytes()); 
      Thread.sleep(100); 
     } 
    } 
} 
2

Utilizo una barra de progreso de "rebote" cuando necesito retrasar una herramienta para evitar una condición de carrera.

private void delay(long milliseconds) { 
    String bar = "[--------------------]"; 
    String icon = "%"; 

    long startTime = new Date().getTime(); 
    boolean bouncePositive = true; 
    int barPosition = 0; 

    while((new Date().getTime() - startTime) < milliseconds) { 
     if(barPosition < bar.length() && barPosition > 0) { 
      String b1 = bar.substring(0, barPosition); 
      String b2 = bar.substring(barPosition); 
      System.out.print("\r Delaying: " + b1 + icon + b2); 
      if(bouncePositive) barPosition++; 
      else barPosition--; 
     } if(barPosition == bar.length()) { 
      barPosition--; 
      bouncePositive = false; 
     } if(barPosition == 0) { 
      barPosition++; 
      bouncePositive = true; 
     } 

     try { Thread.sleep(100); } 
     catch (Exception e) {} 
    } 
    System.out.print("\n"); 
} 
3

Aquí es una versión modificada de lo anterior:

private static boolean loading = true; 
private static synchronized void loading(String msg) throws IOException, InterruptedException { 
    System.out.println(msg); 
    Thread th = new Thread() { 
     @Override 
     public void run() { 
      try { 
       System.out.write("\r|".getBytes()); 
       while(loading) { 
        System.out.write("-".getBytes()); 
        Thread.sleep(500); 
       } 
       System.out.write("| Done \r\n".getBytes()); 
      } catch (IOException e) { 
       e.printStackTrace(); 
      } catch (InterruptedException e) { 
       e.printStackTrace(); 
      } 
     } 
    }; 
    th.start(); 
} 

...y en principal:

loading("Calculating ..."); 
+0

¡Este es un buen ejemplo de Multithreading! Muy útil. – user7185318

2

He hecho un progreso porcentual descubierto para comprobar el archivo de descarga restante.

Llamo periódicamente al método en la descarga de mi archivo para verificar el tamaño total del archivo y el resto y presente en %.

También se puede utilizar para otras tareas.

de prueba y el ejemplo de salida

progressPercentage(0, 1000); 
[----------] 0% 

progressPercentage(10, 100); 
[*---------] 10% 

progressPercentage(500000, 1000000); 
[*****-----] 50% 

progressPercentage(90, 100); 
[*********-] 90% 

progressPercentage(1000, 1000); 
[**********] 100% 

de prueba por bucle

for (int i = 0; i <= 200; i = i + 20) { 
    progressPercentage(i, 200); 
    try { 
     Thread.sleep(500); 
    } catch (Exception e) { 
    } 
} 

El método puede ser fácilmente modificado:

public static void progressPercentage(int remain, int total) { 
    if (remain > total) { 
     throw new IllegalArgumentException(); 
    } 
    int maxBareSize = 10; // 10unit for 100% 
    int remainProcent = ((100 * remain)/total)/maxBareSize; 
    char defaultChar = '-'; 
    String icon = "*"; 
    String bare = new String(new char[maxBareSize]).replace('\0', defaultChar) + "]"; 
    StringBuilder bareDone = new StringBuilder(); 
    bareDone.append("["); 
    for (int i = 0; i < remainProcent; i++) { 
     bareDone.append(icon); 
    } 
    String bareRemain = bare.substring(remainProcent, bare.length()); 
    System.out.print("\r" + bareDone + bareRemain + " " + remainProcent * 10 + "%"); 
    if (remain == total) { 
     System.out.print("\n"); 
    } 
} 
0
while (true) { 
     System.out.write(("\r" + System.currentTimeMillis()).getBytes()); 
     Thread.sleep(1000); 
} 
0
public static void main(String[] argv) throws Exception{ 


    System.out.write("\r".getBytes()); 
    int percentage =10; 
    while(percentage <= 100) { 
     String temp =generateStars(percentage); 
     System.out.write(temp.getBytes()); 
     System.out.print("\b\b\b"); 
     percentage = percentage+10; 
     Thread.sleep(500); 
    } 
} 

    public static String generateStars(int percentage) 
    { 
     int startsNum = percentage/4; 
     StringBuilder builder = new StringBuilder(); 
     while(startsNum >= 0) 
     { 
     builder.append("*"); 
     startsNum--; 
     } 
     builder.append(percentage+"%"); 
     return builder.toString(); 
    } 
2

Recientemente he enfrentado el mismo problema, puede verificar mi código: Lo he configurado para un # en el 5%, que puede modificar más adelante.

public static void main (String[] args) throws java.lang.Exception 
{ 
    int i = 0; 
    while(i < 21) { 
     System.out.print("["); 
     for (int j=0;j<i;j++) { 
      System.out.print("#"); 
     } 

     for (int j=0;j<20-i;j++) { 
      System.out.print(" "); 
     } 

     System.out.print("] "+ i*5 + "%"); 
     if(i<20) { 
      System.out.print("\r"); 
      Thread.sleep(300); 
     } 
     i++; 
    } 
    System.out.println(); 
} 
1

Hay https://github.com/ctongfei/progressbar, Licencia: MIT

simple barra de progreso de la consola. La escritura de la barra de progreso ahora se ejecuta en otro hilo.

Menlo, Fira Mono, Código Fuente Pro o SF Mono se recomiendan para los efectos visuales óptimas.

Para las fuentes Consolas o Andale Mono, use ProgressBarStyle.ASCII (consulte a continuación) porque los glifos de dibujo de cuadro no están alineados correctamente en estas fuentes.

Maven:

<dependency> 
    <groupId>me.tongfei</groupId> 
    <artifactId>progressbar</artifactId> 
    <version>0.5.5</version> 
</dependency> 

Uso:

ProgressBar pb = new ProgressBar("Test", 100); // name, initial max 
// Use ProgressBar("Test", 100, ProgressBarStyle.ASCII) if you want ASCII output style 
pb.start(); // the progress bar starts timing 
// Or you could combine these two lines like this: 
// ProgressBar pb = new ProgressBar("Test", 100).start(); 
some loop { 
    ... 
    pb.step(); // step by 1 
    pb.stepBy(n); // step by n 
    ... 
    pb.stepTo(n); // step directly to n 
    ... 
    pb.maxHint(n); 
    // reset the max of this progress bar as n. This may be useful when the program 
    // gets new information about the current progress. 
    // Can set n to be less than zero: this means that this progress bar would become 
    // indefinite: the max would be unknown. 
    ... 
    pb.setExtraMessage("Reading..."); // Set extra message to display at the end of the bar 
} 
pb.stop() // stops the progress bar 
Cuestiones relacionadas