Baris kemajuan baris perintah di Jawa

130

Saya memiliki program Java yang berjalan dalam mode baris perintah. Saya ingin menampilkan bilah kemajuan, menunjukkan persentase pekerjaan yang dilakukan. Jenis progress bar yang sama akan Anda lihat menggunakan wget di bawah unix. Apakah ini mungkin?

g andrieu
sumber
Saya tidak tahu jawaban untuk pertanyaan spesifik Anda, tetapi Anda bisa mulai dengan memeriksa perpustakaan yang disebutkan dalam pertanyaan ini: stackoverflow.com/questions/435740/…
Jonik
Terima kasih. Perpustakaan dikutip ada lebih banyak tentang parsing argumen command-line, daripada ditampilkan ke konsol. Tapi terima kasih.
g andrieu
7
Ini tentang topik. OP bertanya apakah mungkin, bukan untuk rekomendasi perpustakaan (setidaknya dalam edit saat ini)
Neil McGuigan
Saya mencoba kode ini stackoverflow.com/questions/1001290/… dan berjalan! (Benar hanya berjalan di terminal, jangan gunakan di Eclipse)
Wendel

Jawaban:

176

Saya telah menerapkan hal semacam ini sebelumnya. Ini bukan tentang java, tetapi karakter apa yang harus dikirim ke konsol.

Kuncinya adalah perbedaan antara \ndan \r. \npergi ke awal baris baru. Tetapi \rhanya carriage return - ini kembali ke awal dari baris yang sama.

Jadi yang harus dilakukan adalah mencetak bilah kemajuan Anda, misalnya, dengan mencetak string

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

Pada centang berikutnya dari progress bar, timpa baris yang sama dengan bar yang lebih panjang. (karena kami menggunakan \ r, kami tetap di baris yang sama) Misalnya:

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

Apa yang harus Anda ingat untuk dilakukan, adalah ketika selesai, jika Anda baru saja mencetak

"done!\n"

Anda mungkin masih memiliki beberapa sampah dari bilah progres di telepon. Jadi setelah Anda selesai dengan progress bar, pastikan untuk mencetak spasi yang cukup untuk menghapusnya dari baris. Seperti:

"done             |\n"

Semoga itu bisa membantu.

Matthias Wandel
sumber
Apakah ini benar-benar lintas platform? Mungkin akan berlaku ok pada Windows dan Linux, tetapi bagaimana dengan Mac? Saya tidak punya, jadi saya tidak bisa mencobanya ...
Radu Murzea
2
@ RaduMurzea OS X adalah * NIX OS, jadi jika itu bekerja di Linux, itu akan bekerja pada OS X (itu tidak berlaku untuk semuanya, tapi itu benar di sini).
bfontaine
3
Terima kasih! Namun ini tidak bekerja dengan semut (dicoba di linux dan osx; berfungsi dengan baik ketika memanggil java secara langsung). Adakah yang tahu?
user495285
Perhatikan bahwa ini tidak berfungsi di eclipse built in console (setidaknya untuk saya). Tetapi karena ini adalah konsol pengembangan, ini seharusnya tidak terlalu menjadi masalah.
Qw3ry
Saya menemukan ini: stackoverflow.com/questions/1001290/…
Wendel
46

Ada https://github.com/ctongfei/progressbar , Lisensi: MIT

Bilah progres konsol sederhana. Penulisan progress bar sekarang berjalan di utas lainnya.

Menlo, Fira Mono, Source Code Pro atau SF Mono direkomendasikan untuk efek visual yang optimal.

Untuk font Consolas atau Andale Mono, gunakan ProgressBarStyle.ASCII(lihat di bawah) karena mesin terbang gambar kotak tidak selaras dengan benar dalam font ini.

Maven:

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

Pemakaian:

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
sumber
1
ini terlihat rapi, dan itu akan memungkinkan saya untuk mengganti beberapa ratus baris buffer-string yang saya miliki di CLI saya. Tetapi bagaimana jika saya memiliki aplikasi yang berjalan selama beberapa menit di antara "ticks" (menit di antara step()panggilan)? Apakah perpustakaan Anda berjalan secara tidak sinkron, sehingga memungkinkan jam untuk memperbarui? Bagaimana jika perpustakaan saya berjalan selama berhari-hari? Apakah ini menggunakan /rstrategi? Apakah itu akan menghasilkan keluaran multi-ratus megabyte?
Groostav
23

Saya menemukan kode berikut ini berfungsi dengan benar. Ini menulis byte ke buffer output. Mungkin itu metode menggunakan penulis seperti System.out.println()metode menggantikan kejadian \runtuk \nmencocokkan baris bawaan target berakhir (jika tidak dikonfigurasi dengan benar).

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
sumber
7

Saya telah membuat persentase progres kosong untuk memeriksa file unduhan yang tersisa.

Saya memanggil metode ini secara berkala dalam unduhan file saya untuk memeriksa ukuran file total dan tetap dan menyajikannya %.

Ini dapat digunakan untuk tujuan tugas lain juga.

Contoh uji dan keluaran

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

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

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

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

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

Uji dengan for loop

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

Metode ini dapat dengan mudah dimodifikasi:

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-ɯɐɥʇʎɐɯ
sumber
5

C # Contoh tapi saya menganggap ini sama untuk System.out.printdi Jawa. Jangan ragu untuk mengoreksi saya jika saya salah.

Pada dasarnya, Anda ingin menulis \rkarakter pelarian ke awal pesan Anda yang akan menyebabkan kursor kembali ke awal baris (Umpan Baris) tanpa pindah ke baris berikutnya.

    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
sumber
Contoh yang bagus, pasti akan sangat membantu. Terima kasih.
g andrieu
Cantik! Terima kasih. Bekerja seperti pawang. Mudah dibaca. Indah
kholofelo Maloma
4

Sedikit metode refactored dan updated @ maytham-ɯɐɥʇʎɐɯ. Sekarang ini mendukung ukuran progress bar yang berubah-ubah:

    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
sumber
3

Berikut ini adalah versi modifikasi dari di atas:

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

... dan utama:

loading("Calculating ...");
pengguna3563245
sumber
2

Ini akan dimungkinkan dengan perpustakaan Java Curses. Ini yang saya temukan. Saya belum menggunakannya sendiri dan saya tidak tahu apakah itu cross-platform.

kgiannakakis
sumber
Kutukan mungkin sedikit overhead untuk penggunaan mudah yang saya butuhkan, tapi itu pasti sebuah lagu. Terima kasih.
g andrieu
2

Saya menggunakan bilah kemajuan "memantul" ketika saya harus menunda alat untuk mencegah kondisi balapan.

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
sumber
2

Saya baru-baru ini menghadapi masalah yang sama, Anda dapat memeriksa kode saya: Saya telah menetapkannya untuk # pada 5%, yang dapat Anda modifikasi nanti.

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
sumber
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
sumber
1

Saya mengedit kode Eoin Campbell ke java dan menambahkan kemajuan terformat dalam persen.

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

Dan output:

Generating report...

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

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

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

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

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

Successfully saved 32128 bytes
Marko Štumberger
sumber
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
sumber
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
sumber
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()) + "]";
}

masukkan deskripsi gambar di sini

Nikolay
sumber