web-dev-qa-db-ger.com

Befehlszeilenfortschrittsleiste in Java

Ich habe ein Java-Programm, das im Befehlszeilenmodus ausgeführt wird . Ich möchte eine Fortschrittsleiste anzeigen, die den Prozentsatz der erledigten Jobs angibt . Die gleiche Art von Fortschrittsleiste, die Sie mit wget unter unix ..__ sehen würden. Ist das möglich?

109
g andrieu

Ich habe so etwas schon mal umgesetzt. Es geht nicht so sehr um Java, sondern um die Zeichen, die an die Konsole gesendet werden sollen.

Der Schlüssel ist der Unterschied zwischen \n und \r.\n geht an den Anfang einer neuen Zeile. Aber \r ist nur Wagenrücklauf - es geht zum Anfang derselben Zeile zurück.

Sie müssen Ihren Fortschrittsbalken beispielsweise durch Drucken der Zeichenfolge drucken

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

Überschreiben Sie beim nächsten Tick des Fortschrittsbalkens dieselbe Zeile mit einem längeren Balken. (Da wir\r verwenden, bleiben wir in derselben Zeile.) Zum Beispiel:

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

Was Sie beachten müssen, ist, wenn Sie fertig sind, wenn Sie dann nur noch drucken

"done!\n"

Möglicherweise enthält der Fortschrittsbalken in der Zeile noch etwas Müll. Wenn Sie mit der Fortschrittsleiste fertig sind, stellen Sie sicher, dass Sie genügend Leerzeichen drucken, um sie aus der Zeile zu entfernen. Sowie:

"done             |\n"

Hoffentlich hilft das.

156
Matthias Wandel

Es gibt https://github.com/ctongfei/progressbar , Lizenz: MIT

Einfache Konsolenfortschrittsleiste. Das Fortschrittsbalkenschreiben läuft jetzt in einem anderen Thread.

Für optimale visuelle Effekte werden Menlo, Fira Mono, Source Code Pro oder SF Mono empfohlen.

Verwenden Sie für Consolas- oder Andale Mono-Schriftarten ProgressBarStyle.ASCII (siehe unten), da die Glyphen für die Box-Zeichnung in diesen Schriftarten nicht richtig ausgerichtet sind.

Maven:

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

Verwendungszweck:

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
24
koppor

Ich habe festgestellt, dass der folgende Code korrekt funktioniert. Es schreibt Bytes in den Ausgabepuffer. Möglicherweise ersetzt diese Methode, die einen Writer wie die System.out.println()-Methode verwendet, die Vorkommen von \r in \n, um mit dem ursprünglichen Zeilenende des Ziels übereinzustimmen (falls nicht ordnungsgemäß konfiguriert). 

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);
        }
    }
}
21
keesj

Ich habe einen prozentualen Fortschritt gemacht, um die verbleibende Download-Datei zu überprüfen.

Ich rufe die Methode regelmäßig in meinem Dateidownload auf, um die Gesamtdateigröße zu überprüfen und die verbleibende Größe in % anzuzeigen.

Es kann auch für andere Aufgaben verwendet werden.

Test- und Ausgabebeispiel

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

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

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

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

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

Testen Sie mit for-Schleife

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

Die Methode kann leicht geändert werden:

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");
    }
}

C # -Beispiel, aber ich gehe davon aus, dass dies für System.out.print in Java das gleiche ist Fühlen Sie sich frei, mich zu korrigieren, wenn ich falsch liege.

Grundsätzlich möchten Sie das \r-Escape-Zeichen an den Anfang Ihrer Nachricht Schreiben, wodurch der Cursor zum Anfang der Zeile (Zeilenvorschub) zurückkehrt, ohne zur nächsten Zeile zu wechseln.

    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();

    }
5
Eoin Campbell

Hier ist eine modifizierte Version des Obigen:

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();
}

... und hauptsächlich:

loading("Calculating ...");
3
user3563245

Ich habe kürzlich das gleiche Problem gesehen, Sie können meinen Code überprüfen: Ich habe ihn für eine # auf 5% gesetzt, die Sie später ändern können.

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();
}
2
Aashutosh Rathi

Ich verwende einen Fortschrittsbalken, wenn ich ein Werkzeug verzögern muss, um einen Rennzustand zu verhindern.

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");
}
2
mkeathley

Dies wäre mit einer Java-Curses-Bibliothek möglich. Das habe ich gefunden. Ich habe es selbst nicht benutzt und ich weiß nicht, ob es plattformübergreifend ist.

2
kgiannakakis

Ein bisschen überarbeitet und @ maytham-ɯɐɥʇʎɐɯ Methode aktualisiert. Jetzt unterstützt es eine beliebige Größe des Fortschrittsbalkens:

    public static void progressPercentage(int done, int total) {
        int size = 5;
        String iconLeftBoundary = "[";
        String iconDone = "=";
        String iconRemain = ".";
        String iconRightBoundary = "]";

        if (done > total) {
            throw new IllegalArgumentException();
        }
        int donePercents = (100 * done) / total;
        int doneLength = size * donePercents / 100;

        StringBuilder bar = new StringBuilder(iconLeftBoundary);
        for (int i = 0; i < size; i++) {
            if (i < doneLength) {
                bar.append(iconDone);
            } else {
                bar.append(iconRemain);
            }
        }
        bar.append(iconRightBoundary);

        System.out.print("\r" + bar + " " + donePercents + "%");

        if (done == total) {
            System.out.print("\n");
        }
    }
1
Dennis
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();
    }
0
vootla561
public class Main {

    public static void main(String[] args) throws Exception {

        System.out.println("Loading : ");
            int count =1;
            for(int j=1;j<150;j++){

                System.out.print("\r");
                if(count==1){
                    System.out.print("/");
                    count++;
                }
                else if(count==2){
                    System.out.print("|");
                    count++;
                }
                else if(count==3){
                    System.out.print("-");
                    count++;
                }
                else if(count==4){
                    System.out.print("\\");
                    count++;
                }
                else if(count==5){
                    System.out.print("|");
                    count++;
                }
                else
                    count = 1;
            Thread.sleep(200);
        }

        }

    }
0
Arun Joshla
public class ProgressBar
{
    private int max;

    public ProgressBar(int max0) {
        max = max0;
        update(0);
    }

    public void update(int perc) {
        String toPrint = "|";
        for(int i = 0; i < max; i++) {
            if(i <= (perc + 1))
                toPrint += "=";
            else
                toPrint += " ";
        }

        if(perc >= max)
            Console.print("\r");
        else
            Console.print(toPrint + "|\r");
    }
}
0
Deplover