Thanh tiến trình dòng lệnh trong Java


130

Tôi có một chương trình Java đang chạy trong chế độ dòng lệnh. Tôi muốn hiển thị một thanh tiến trình, hiển thị phần trăm công việc được thực hiện. Loại thanh tiến trình tương tự bạn sẽ thấy bằng cách sử dụng wget dưới unix. Điều này có thể không?


Tôi không biết câu trả lời cho câu hỏi cụ thể của bạn, nhưng bạn có thể bắt đầu bằng cách kiểm tra các thư viện được đề cập trong câu hỏi này: stackoverflow.com/questions/435740/
Kẻ

Cảm ơn. Các thư viện được trích dẫn có nhiều hơn về phân tích đối số dòng lệnh, thay vì hiển thị vào bàn điều khiển. Nhưng dù sao cũng cảm ơn.
g andrieu

7
Đây là về chủ đề. OP hỏi nếu có thể, không phải cho một đề xuất thư viện (ít nhất là trong bản chỉnh sửa hiện tại)
Neil McGuigan

Tôi thử mã stackoverflow.com/questions/1001290/ này và chạy! (Chỉ chạy đúng trong thiết bị đầu cuối, không sử dụng trong Eclipse)
Wendel

Câu trả lời:


176

Tôi đã thực hiện loại điều này trước đây. Nó không quá nhiều về java, nhưng những nhân vật để gửi đến giao diện điều khiển.

Điều quan trọng là sự khác biệt giữa \n\r. \nđi đến bắt đầu của một dòng mới. Nhưng \rchỉ là trở về vận chuyển - nó trở lại bắt đầu của cùng một dòng.

Vì vậy, điều cần làm là in thanh tiến trình của bạn, ví dụ, bằng cách in chuỗi

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

Trên đánh dấu tiếp theo của thanh tiến trình, ghi đè lên cùng một dòng với một thanh dài hơn. (vì chúng tôi đang sử dụng \ r, chúng tôi vẫn ở trên cùng một dòng) Ví dụ:

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

Những gì bạn phải nhớ, là khi hoàn thành, nếu bạn chỉ cần in

"done!\n"

Bạn vẫn có thể có một số rác từ thanh tiến trình trên dòng. Vì vậy, sau khi bạn hoàn thành thanh tiến trình, hãy nhớ in đủ khoảng trắng để xóa nó khỏi dòng. Nhu la:

"done             |\n"

Mong rằng sẽ giúp.


Đây thực sự là đa nền tảng? Nó có thể sẽ hoạt động tốt trên Windows và Linux, nhưng với máy Mac thì sao? Tôi không có, vì vậy tôi không thể thử ...
Radu Murzea

2
@RaduMurzea OS X là hệ điều hành * NIX, vì vậy nếu nó hoạt động trên Linux, nó sẽ hoạt động trên OS X (điều đó không đúng với mọi thứ, nhưng điều đó đúng ở đây).
bfontaine

3
Cảm ơn! Tuy nhiên, điều này không hoạt động với ant (đã thử trên cả linux và osx; hoạt động tốt khi gọi java trực tiếp). Bất cứ ai có ý tưởng?
dùng495285

Lưu ý rằng điều này không hoạt động trong nhật thực được xây dựng trong bảng điều khiển (ít nhất là đối với tôi). Nhưng vì đây là bảng điều khiển phát triển nên điều này không quá quan trọng.
Qw3ry

Tôi đã tìm thấy cái này: stackoverflow.com/questions/1001290/
Kẻ

46

https://github.com/ctongfei/proTHERbar , Giấy phép: MIT

Thanh tiến trình điều khiển đơn giản. Tiến trình viết thanh bây giờ chạy trên một chủ đề khác.

Menlo, Fira Mono, Source Code Pro hoặc SF Mono được khuyến nghị cho các hiệu ứng hình ảnh tối ưu.

Đối với các phông chữ Consolas hoặc Andale Mono, hãy sử dụng ProgressBarStyle.ASCII(xem bên dưới) vì các glyph vẽ hình hộp không được căn chỉnh chính xác trong các phông chữ này.

Maven:

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

Sử dụng:

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
cái này trông gọn gàng và nó sẽ cho phép tôi thay thế vài trăm dòng bộ đệm chuỗi mà tôi đã có trên CLI của mình. Nhưng điều gì sẽ xảy ra nếu tôi có một ứng dụng chạy trong vài phút giữa các "tích tắc" (phút giữa step()các cuộc gọi)? Có phải thư viện của bạn chạy không đồng bộ, do đó cho phép đồng hồ cập nhật? Nếu thư viện của tôi chạy trong nhiều ngày thì sao? Liệu nó có sử dụng /rchiến lược? Điều đó sẽ dẫn đến sản lượng hàng trăm megabyte?
Groostav

23

Tôi tìm thấy đoạn mã sau để hoạt động chính xác. Nó ghi byte vào bộ đệm đầu ra. Có lẽ rằng phương pháp sử dụng một nhà văn như System.out.println()phương pháp thay thế xuất hiện của \rđể \ncho phù hợp với dòng mẹ đẻ của mục tiêu kết thúc (nếu không được cấu hình đúng cách).

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

Tôi đã thực hiện một phần trăm tiến độ trần để kiểm tra tệp tải xuống vẫn còn.

Tôi gọi phương thức định kỳ trong phần tải xuống tệp của mình để kiểm tra tổng kích thước tệp và phần còn lại và trình bày trong % .

Nó có thể được sử dụng cho mục đích nhiệm vụ khác là tốt.

Ví dụ kiểm tra và đầu ra

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

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

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

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

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

Kiểm tra với vòng lặp

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

Phương pháp có thể dễ dàng sửa đổi:

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

Ví dụ về C # nhưng tôi cho rằng điều này giống với System.out.print trong Java. Hãy sửa tôi nếu tôi sai.

Về cơ bản, bạn muốn viết \rký tự thoát vào đầu tin nhắn của mình, điều này sẽ khiến con trỏ trở về đầu dòng (Nguồn cấp dữ liệu) mà không chuyển sang dòng tiếp theo.

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

    }

Ví dụ tốt đẹp, chắc chắn sẽ hữu ích. Cảm ơn.
g andrieu

Xinh đẹp! Cảm ơn bạn. Hoạt động như một người quyến rũ. Dễ đọc. Đáng yêu
kholofelo Maloma 7/07/2016

4

Một chút được tái cấu trúc và cập nhật phương thức @ maytham-'. Bây giờ, nó hỗ trợ một kích thước tùy ý của thanh tiến trình:

    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

Đây là một phiên bản sửa đổi ở trên:

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

... và chính:

loading("Calculating ...");

2

Điều này có thể xảy ra với thư viện Java Curses. Đây là những gì tôi đã tìm thấy. Tôi đã không sử dụng nó cho mình và tôi không biết nếu nó là đa nền tảng.


Những lời nguyền có thể là một chút chi phí cho việc sử dụng dễ dàng mà tôi cần, nhưng đó chắc chắn là một bản nhạc. Cảm ơn.
g andrieu

2

Tôi sử dụng thanh tiến trình "nảy" khi tôi cần trì hoãn một công cụ để ngăn chặn tình trạng cuộc đua.

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

Gần đây tôi đã gặp phải vấn đề tương tự, bạn có thể kiểm tra mã của mình: Tôi đã đặt nó cho một # trên 5%, mà bạn có thể sửa đổi sau này.

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

Tôi đã chỉnh sửa mã của Eoin Campbell thành java và thêm tiến trình được định dạng trong phần trăm.

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

Và đầu ra:

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

nhập mô tả hình ảnh ở đây

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.