2009-06-16 16 views
31

Gibt es eine einfache Möglichkeit, einen Rolling-Prozentsatz für einen Prozess in Java zu implementieren, der in der Konsole angezeigt werden soll? Ich habe einen prozentualen Datentyp (double), den ich während eines bestimmten Prozesses generiert habe. Kann ich ihn jedoch in das Konsolenfenster zwingen und aktualisieren lassen, anstatt nur eine neue Zeile für jede neue Aktualisierung auf den Prozentsatz zu drucken? Ich habe darüber nachgedacht, ein cls zu pushen und zu aktualisieren, weil ich in einer Windows-Umgebung arbeite, aber ich hatte gehofft, dass Java eine Art eingebauter Fähigkeit hatte. Alle Vorschläge sind willkommen! Vielen Dank!Konsolenbasierter Fortschritt in Java

+1

Für die Aufzeichnung eine eng verwandte ältere Frage zu verwenden: http://stackoverflow.com/questions/852665/command-line-progress-bar-in-java – Jonik

Antwort

51

Sie können einen Wagenrücklauf drucken \r den Cursor an den Anfang der Zeile zu setzen.

Beispiel:

public class ProgressDemo { 
    static void updateProgress(double progressPercentage) { 
    final int width = 50; // progress bar width in chars 

    System.out.print("\r["); 
    int i = 0; 
    for (; i <= (int)(progressPercentage*width); i++) { 
     System.out.print("."); 
    } 
    for (; i < width; i++) { 
     System.out.print(" "); 
    } 
    System.out.print("]"); 
    } 

    public static void main(String[] args) { 
    try { 
     for (double progressPercentage = 0.0; progressPercentage < 1.0; progressPercentage += 0.01) { 
     updateProgress(progressPercentage); 
     Thread.sleep(20); 
     } 
    } catch (InterruptedException e) {} 
    } 
} 
+5

Ich habe gerade versucht, dass . Es funktioniert nicht. (Getestet in Eclipse.) –

+0

@David Johnstone: Das obige Beispiel funktioniert zumindest in herkömmlichen Konsolenfenstern. – laalto

+0

@laalto: Yup, versuchte es in einem normalen Konsolenfenster und es funktionierte für mich. – Michael

6

Ich glaube nicht, dass es eine eingebaute Fähigkeit zu tun, was Sie suchen.

Es gibt eine Bibliothek, die es tun wird (JLine).

Sehen Sie diese tutorial

4

ich ziemlich sicher bin, gibt es keine Möglichkeit, etwas zu ändern ist, dass die Konsole gedruckt wurde bereits da Java die Konsole (Standard out) hält ein Print zu sein.

0

Deaktivieren Sie die Konsole, indem Sie den os spezifischen Befehl ausführen und drucken Sie dann den neuen Prozentsatz

8

Ich verwende folgenden Code:

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(current == 0 ? (int) (Math.log10(total)) : (int) (Math.log10(total)) - (int) (Math.log10(current)), " "))) 
     .append(String.format(" %d/%d, ETA: %s", current, total, etaHms)); 

    System.out.print(string); 
} 

Das Ergebnis: enter image description here

+2

Wow! Vielen Dank! Für mich funktioniert es wirklich gut und besser, als markierte Antwort. –

+0

Nur eine Anmerkung für andere, wenn Sie Ihre for-Schleife mit 'i = 0 'starten, erhalten Sie möglicherweise eine IllegalArgumentException von diesem Code. Ansonsten wirkt ein Charme. –

+1

Das schien nicht richtig für mich zu funktionieren.Ich kopierte es genau, und anstatt der Fortschrittsbalken in der gleichen Zeile zu bleiben, druckte es neue Zeilen für jeden. – jeshbreadnan

0
import java.util.Random; 

public class ConsoleProgress { 

    private static String CURSOR_STRING = "0%.......10%.......20%.......30%.......40%.......50%.......60%.......70%.......80%.......90%.....100%"; 

    private static final double MAX_STEP = CURSOR_STRING.length() - 1; 

    private double max; 
    private double step; 
    private double cursor; 
    private double lastCursor; 

    public static void main(String[] args) throws InterruptedException { 
     // --------------------------------------------------------------------------------- 
     int max = new Random().nextInt(400) + 1; 
     // --------------------------------------------------------------------------------- 
     // Example of use : 
     // --------------------------------------------------------------------------------- 
     ConsoleProgress progress = new ConsoleProgress("Progress (" + max + ") : ", max); 
     for (int i = 1; i <= max; i++, progress.nextProgress()) { 
      Thread.sleep(3L); // a task with no prints 
     } 
    } 

    public ConsoleProgress(String title, int maxCounts) { 
     cursor = 0.; 
     max = maxCounts; 
     step = MAX_STEP/max; 
     System.out.print(title); 
     printCursor(); 
     nextProgress(); 
    } 

    public void nextProgress() { 
     printCursor(); 
     cursor += step; 
    } 

    private void printCursor() { 
     int intCursor = (int) Math.round(cursor) + 1; 
     System.out.print(CURSOR_STRING.substring((int) lastCursor, intCursor)); 
     if (lastCursor != intCursor && intCursor == CURSOR_STRING.length()) 
      System.out.println(); // final print 
     lastCursor = intCursor; 
    } 
} 
+0

Dies wird auf EINZEL Zeile in Java-Konsole – Elphara77

+0

sowie in Eclipse-Konsole angezeigt – Elphara77

0

spät für die Partei, aber hier ist eine Antwort:

public static String getSingleLineProgress(double progress) { 
    String progressOutput = "Progress: |"; 
    String padding = Strings.padEnd("", (int) Math.ceil(progress/5), '='); 
    progressOutput += Strings.padEnd(padding, 0, ' ') + df.format(progress) + "%|\r"; 
    if (progress == 100.0D) { 
     progressOutput += "\n"; 
    } 
    return progressOutput; 
} 

Denken Sie daran, System.out.print() statt System.out.println()