Javaのコマンドラインプログレスバー


130

コマンドラインモードでJavaプログラムを実行しています。完了したジョブの割合を示すプログレスバーを表示したいと思います。UNIXでwgetを使用する場合と同じ種類の進行状況バー。これは可能ですか?


私はあなたの特定の質問への答えを知らないが、あなたはこの質問に記載されたライブラリをチェックすることから始めることができます:stackoverflow.com/questions/435740/...
Jonikを

ありがとう。そこに引用されているライブラリは、コンソールに表示するのではなく、コマンドライン引数の解析についての詳細です。しかしとにかくありがとう。
g andrieu

7
これは話題です。OPは、可能であれば、ライブラリの推奨事項ではなく(少なくとも現在の編集では)尋ねます
Neil McGuigan 2016年

私はこのコードstackoverflow.com/questions/1001290/…を試して実行しています!(ターミナルでのみ正しく実行され、Eclipseでは使用しないでください)
Wendel

回答:


176

このようなことを以前に実装しました。これはJavaについてはそれほどではなく、コンソールに送信する文字です。

キーは間の差である\n\r\n新しい行の先頭に移動します。ただし、キャリッジリターン\rのみです。同じ行の先頭に戻ります。

したがって、やるべきことは、たとえば、文字列を印刷することによって、プログレスバーを印刷することです

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

プログレスバーの次の目盛りで、同じ行を長いバーで上書きします。(\ rを使用しているため、同じ行にとどまります)例:

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

あなたがしなければならないことは、いつ印刷するかということです。

"done!\n"

行のプログレスバーからまだごみが残っている可能性があります。そのため、プログレスバーを使い終わったら、行から削除するのに十分な空白を印刷してください。といった:

"done             |\n"

お役に立てば幸いです。


これは本当にクロスプラットフォームですか?おそらくWindowsとLinuxでは問題なく動作しますが、Macはどうでしょうか?私は持っていないので、試すことができません...
Radu Murzea 2013年

2
@RaduMurzea OS Xは* NIX OSであるため、Linuxで動作する場合、OS Xで動作します(すべてに当てはまるわけではありませんが、ここでは当てはまります)。
bfontaine 2013年

3
ありがとう!ただし、これはantでは機能しません(linuxとosxの両方で試してみました。javaを直接呼び出すと正常に機能します)。誰かアイデアはありますか?
user495285 2014

これは、(少なくとも私にとっては)Eclipseの組み込みコンソールでは機能しないことに注意してください。しかし、これは開発コンソールなので、あまり問題にしないでください。
Qw3ry 2017


46

https://github.com/ctongfei/progressbarがあります。ライセンス:MIT

シンプルなコンソールプログレスバー。進行状況バーの書き込みが別のスレッドで実行されるようになりました。

最適な視覚効果を得るには、Menlo、Fira Mono、Source Code Pro、またはSF Monoをお勧めします。

ConsolasまたはAndale MonoフォントではProgressBarStyle.ASCII、ボックス描画グリフがこれらのフォントで適切に配置されていないため、以下を参照してください。

Maven:

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

使用法:

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

1
これは見栄えがよく、CLIで取得した数百の文字列バッファ行を置き換えることができます。しかし、「ティック」の間の数分間(step()呼び出しの間の分)実行されるアプリケーションがある場合はどうなりますか?ライブラリは非同期で実行されるため、クロックを更新できますか?ライブラリが数日間実行されるとどうなりますか?/r戦略を使用していますか?その結果、数百メガバイトの出力になりますか?
Groostav、

23

次のコードが正しく機能することがわかりました。バイトを出力バッファに書き込みます。おそらく、メソッドのようなライターを使用するSystem.out.println()メソッドは、\rto の出現を置き換えて\n、ターゲットのネイティブの行末と一致します(適切に構成されていない場合)。

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

7

残りのダウンロードファイルを確認するために、パーセンテージの進捗を最小限に抑えました。

ファイルのダウンロードで定期的にメソッドを呼び出して、合計ファイルサイズと残りのサイズを確認し、それをに表示し%ます。

他のタスクの目的にも使用できます。

テストと出力の例

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

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

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

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

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

forループでテストする

for (int i = 0; i <= 200; i = i + 20) {
    progressPercentage(i, 200);
    try {
        Thread.sleep(500);
    } catch (Exception 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");
    }
}

5

C#の例ですが、これはSystem.out.printJava でも同じだと思います。私が間違っている場合は、遠慮なく訂正してください。

基本的に、\rメッセージの先頭にエスケープ文字を書き出すと、カーソルが次の行に移動せずに行の先頭(改行)に戻ります。

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

    }

良い例は、確かに役に立ちます。ありがとう。
g andrieu

綺麗な!ありがとうございました。魔法使いのように動作します。読みやすい。素敵
kholofelo Maloma 2016

4

少しリファクタリングされ、@maytham-ɯɐɥʇʎɐɯのメソッドが更新されました。これで、進行状況バーの任意のサイズがサポートされます。

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

3

上記の修正バージョンは次のとおりです。

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

...そして主に:

loading("Calculating ...");

2

これは、Java Cursesライブラリで可能です。これは私が見つけたものです。私はそれを自分で使用したことがなく、クロスプラットフォームかどうかはわかりません。


呪いは、私が必要とする簡単な使用法のオーバーヘッドの少しかもしれませんが、それは確かにトラックです。ありがとう。
g andrieu

2

競合状態を防ぐためにツールを遅らせる必要がある場合は、「バウンス」プログレスバーを使用します。

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

私は最近同じ問題に直面しました。私のコードを確認できます。5%の#に1つ設定しました。後で変更できます。

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

1

Eoin CampbellのコードをJavaに編集し、フォーマットされた進行状況をパーセントで追加しました。

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

そして出力:

Generating report...

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

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

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

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

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

Successfully saved 32128 bytes

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

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

        }

    }

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

ここに画像の説明を入力してください

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.