2011-01-01 19 views
23

Me gustaría agregar un indicador de progreso a un programa Java de línea de comandos.Java: Actualización de texto en la línea de comandos sin una nueva línea

Por ejemplo, si estoy usando wget, que muestra:

71% [===========================>   ] 358,756,352 51.2M/s eta 3s 

¿Es posible tener un indicador de progreso que las actualizaciones sin necesidad de añadir una nueva línea en la parte inferior?

Gracias.

+0

@rfeak Lo sentimos, http://stackoverflow.com/questions/1001290/console-based-progress-in-java – TheLQ

Respuesta

27

Primero, cuando escriba, no use writeln(). Use write(). En segundo lugar, puede usar "\ r" para Retorno de carro sin utilizar \ n que es una línea nueva. El retorno de carro debe devolverlo al comienzo de la línea.

+7

Pero si la longitud del texto puede reducirse (por ejemplo, la cantidad de dígitos necesarios para mostrar el ETA disminuye), recuerde escribir espacios sobre los caracteres antiguos para que no aparezcan más. EDITAR: Además, recuerde hacer System.out.flush() para asegurarse de que el texto realmente se muestre (por ejemplo, en un terminal con buffer de línea). – jstanley

+0

@jstanley - Buenos puntos para recordar. – rfeak

23

utilizo siguiente código:

public static void main(String[] args) { 
    long total = 235; 
    long startTime = System.currentTimeMillis(); 

    for (int i = 1; i <= total; i = i + 3) { 
     try { 
      Thread.sleep(50); 
      printProgress(startTime, total, i); 
     } catch (InterruptedException e) { 
     } 
    } 
} 


private static void printProgress(long startTime, long total, long current) { 
    long eta = current == 0 ? 0 : 
     (total - current) * (System.currentTimeMillis() - startTime)/current; 

    String etaHms = current == 0 ? "N/A" : 
      String.format("%02d:%02d:%02d", TimeUnit.MILLISECONDS.toHours(eta), 
        TimeUnit.MILLISECONDS.toMinutes(eta) % TimeUnit.HOURS.toMinutes(1), 
        TimeUnit.MILLISECONDS.toSeconds(eta) % TimeUnit.MINUTES.toSeconds(1)); 

    StringBuilder string = new StringBuilder(140); 
    int percent = (int) (current * 100/total); 
    string 
     .append('\r') 
     .append(String.join("", Collections.nCopies(percent == 0 ? 2 : 2 - (int) (Math.log10(percent)), " "))) 
     .append(String.format(" %d%% [", percent)) 
     .append(String.join("", Collections.nCopies(percent, "="))) 
     .append('>') 
     .append(String.join("", Collections.nCopies(100 - percent, " "))) 
     .append(']') 
     .append(String.join("", Collections.nCopies((int) (Math.log10(total)) - (int) (Math.log10(current)), " "))) 
     .append(String.format(" %d/%d, ETA: %s", current, total, etaHms)); 

    System.out.print(string); 
} 

El resultado: enter image description here

Cuestiones relacionadas