Barre de progression de la ligne de commande en Java

130

J'ai un programme Java fonctionnant en mode ligne de commande. Je voudrais afficher une barre de progression, indiquant le pourcentage de travail effectué. Le même type de barre de progression que vous verriez en utilisant wget sous unix. Est-ce possible?

g andrieu
la source
Je ne connais pas la réponse à votre question spécifique, mais vous pouvez commencer par vérifier les bibliothèques mentionnées dans cette question: stackoverflow.com/questions/435740/…
Jonik
Merci. Les bibliothèques citées ici concernent davantage l'analyse des arguments de ligne de commande que l'affichage dans la console. Mais merci quand même.
g andrieu
7
C'est sur le sujet. OP demande si possible, pas pour une recommandation de la bibliothèque (du moins dans l'édition actuelle)
Neil McGuigan
J'essaye ce code stackoverflow.com/questions/1001290/… et en cours d'exécution! (Exécution correcte uniquement dans le terminal, ne pas utiliser dans Eclipse)
Wendel

Réponses:

176

J'ai déjà implémenté ce genre de chose. Ce n'est pas tant une question de java, mais de quels caractères envoyer à la console.

La clé est la différence entre \net \r. \nva au début d'une nouvelle ligne. Mais ce \rn'est qu'un retour chariot - il revient au début de la même ligne.

Donc la chose à faire est d'imprimer votre barre de progression, par exemple, en imprimant la chaîne

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

Au prochain tick de la barre de progression, écrasez la même ligne par une barre plus longue. (parce que nous utilisons \ r, nous restons sur la même ligne) Par exemple:

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

Ce que vous devez vous rappeler de faire, c'est lorsque vous avez terminé, si vous imprimez simplement

"done!\n"

Vous pouvez toujours avoir des déchets de la barre de progression sur la ligne. Donc, une fois que vous avez terminé avec la barre de progression, assurez-vous d'imprimer suffisamment d'espaces pour la supprimer de la ligne. Tel que:

"done             |\n"

J'espère que cela pourra aider.

Matthias Wandel
la source
Est-ce vraiment multiplateforme? Il se comportera probablement correctement sous Windows et Linux, mais qu'en est-il des Mac? Je n'en ai pas, donc je ne peux pas l'essayer ...
Radu Murzea
2
@RaduMurzea OS X est un système d'exploitation * NIX, donc s'il fonctionne sous Linux, il fonctionnera sous OS X (ce n'est pas vrai pour tout, mais c'est vrai ici).
bfontaine le
3
Merci! Cependant, cela ne fonctionne pas avec ant (essayé à la fois sous linux et osx; fonctionne bien lors de l'appel direct de java). Quelqu'un a une idée?
user495285
Notez que cela ne fonctionne pas dans la console intégrée eclipse (du moins pour moi). Mais comme il s'agit d'une console de développement, cela ne devrait pas avoir trop d'importance.
Qw3ry
J'ai trouvé ceci: stackoverflow.com/questions/1001290/…
Wendel
46

Il existe https://github.com/ctongfei/progressbar , Licence: MIT

Barre de progression de la console simple. L'écriture de la barre de progression s'exécute maintenant sur un autre thread.

Menlo, Fira Mono, Source Code Pro ou SF Mono sont recommandés pour des effets visuels optimaux.

Pour les polices Consolas ou Andale Mono, utilisez ProgressBarStyle.ASCII(voir ci-dessous) car les glyphes de dessin de boîte ne sont pas correctement alignés dans ces polices.

Maven:

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

Usage:

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
Koppor
la source
1
cela a l'air soigné, et cela me permettra de remplacer quelques centaines de lignes de tampon de chaîne que j'ai sur ma CLI. Mais que faire si j'ai une application qui fonctionne pendant des minutes entre les "ticks" (minutes entre les step()appels)? Votre bibliothèque fonctionne-t-elle de manière asynchrone, permettant ainsi à l'horloge de se mettre à jour? Et si ma bibliothèque fonctionnait pendant des jours? Utilise-t-il la /rstratégie? Cela entraînera-t-il une sortie de plusieurs centaines de mégaoctets?
Groostav
23

J'ai trouvé le code suivant pour fonctionner correctement. Il écrit des octets dans le tampon de sortie. Peut-être que les méthodes utilisant un rédacteur comme la System.out.println()méthode remplace les occurrences de \rto \npour correspondre à la fin de ligne native de la cible (si elle n'est pas configurée correctement).

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

J'ai fait un pourcentage de progrès à nu pour vérifier le fichier de téléchargement restant.

J'appelle la méthode périodiquement dans mon téléchargement de fichier pour vérifier la taille totale du fichier et la taille restante et la présenter au format %.

Il peut également être utilisé à d'autres fins.

Exemple de test et de sortie

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

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

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

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

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

Test avec boucle for

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

La méthode peut être facilement modifiée:

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");
    }
}
maytham-ɯɐɥʇʎɐɯ
la source
5

Exemple C # mais je suppose que c'est la même chose pour System.out.printJava. N'hésitez pas à me corriger si je me trompe.

Fondamentalement, vous souhaitez écrire le \rcaractère d'échappement au début de votre message, ce qui fera revenir le curseur au début de la ligne (saut de ligne) sans passer à la ligne suivante.

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

    }
Eoin Campbell
la source
Bel exemple, sera certainement utile. Merci.
g andrieu
Belle! Je vous remercie. Fonctionne comme un charmeur. Facile à lire. Lovely
kholofelo Maloma
4

Un peu refactorisé et mis à jour la méthode de @ maytham-ɯɐɥʇʎɐɯ. Maintenant, il prend en charge une taille arbitraire de la barre de progression:

    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");
        }
    }
Dennis
la source
3

Voici une version modifiée de ce qui précède:

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

... et en général:

loading("Calculating ...");
user3563245
la source
2

Cela serait possible avec une bibliothèque Java Curses. C'est ce que j'ai trouvé. Je ne l'ai pas utilisé moi-même et je ne sais pas si c'est multiplateforme.

kgiannakakis
la source
Les malédictions peuvent être un peu trop lourdes pour l'utilisation facile dont j'ai besoin, mais c'est certainement une piste. Merci.
g andrieu
2

J'utilise une barre de progression "rebondissante" lorsque je dois retarder un outil pour éviter une condition de concurrence.

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

J'ai récemment rencontré le même problème, vous pouvez vérifier mon code: je l'ai défini pour un # sur 5%, que vous pourrez modifier plus tard.

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();
}
Aashutosh Rathi
la source
1
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();
    }
vootla561
la source
1

J'ai édité le code d'Eoin Campbell en java et ajouté une progression formatée en pourcentages.

public static String progressBar(int currentValue, int maxValue) {
    int progressBarLength = 33; //
    if (progressBarLength < 9 || progressBarLength % 2 == 0) {
        throw new ArithmeticException("formattedPercent.length() = 9! + even number of chars (one for each side)");
    }
    int currentProgressBarIndex = (int) Math.ceil(((double) progressBarLength / maxValue) * currentValue);
    String formattedPercent = String.format(" %5.1f %% ", (100 * currentProgressBarIndex) / (double) progressBarLength);
    int percentStartIndex = ((progressBarLength - formattedPercent.length()) / 2);

    StringBuilder sb = new StringBuilder();
    sb.append("[");
    for (int progressBarIndex = 0; progressBarIndex < progressBarLength; progressBarIndex++) {
        if (progressBarIndex <= percentStartIndex - 1
        ||  progressBarIndex >= percentStartIndex + formattedPercent.length()) {
            sb.append(currentProgressBarIndex <= progressBarIndex ? " " : "=");
        } else if (progressBarIndex == percentStartIndex) {
            sb.append(formattedPercent);
        }
    }
    sb.append("]");
    return sb.toString();
}

int max = 22;
System.out.println("Generating report...");
for (int i = 0; i <= max; i++) {
   Thread.sleep(100);
   System.out.print(String.format("\r%s", progressBar(i, max)));
}
System.out.println("\nSuccessfully saved 32128 bytes");

Et sortie:

Generating report...

[========      24.2 %             ]

[============  45.5 %             ]

[============  78.8 % =====       ]

[============  87.9 % ========    ]

[============ 100.0 % ============]

Successfully saved 32128 bytes
Marko Štumberger
la source
0
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");
    }
}
Lurzapps
la source
0
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);
        }

        }

    }
Arun Joshla
la source
0
static String progressBar(int progressBarSize, long currentPosition, long startPositoin, long finishPosition) {
    String bar = "";
    int nPositions = progressBarSize;
    char pb = '░';
    char stat = '█';
    for (int p = 0; p < nPositions; p++) {
        bar += pb;
    }
    int ststus = (int) (100 * (currentPosition - startPositoin) / (finishPosition - startPositoin));
    int move = (nPositions * ststus) / 100;
    return "[" + bar.substring(0, move).replace(pb, stat) + ststus + "%" + bar.substring(move, bar.length()) + "]";
}

entrez la description de l'image ici

Nikolay
la source