2009-05-12 44 views
87

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

+0

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 nêu tại câu hỏi này : http://stackoverflow.com/questions/435740/are-there-good-java-libraries-that-facilitate-building-command-line-applications – Jonik

+0

Cảm ơn. Các thư viện được trích dẫn có nhiều hơn về phân tích cú pháp đối số dòng lệnh, thay vì hiển thị trong bảng điều khiển. Nhưng cảm ơn anyways. –

+6

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

Trả lời

132

Tôi đã triển khai loại điều này trước đây. Nó không quá nhiều về java, nhưng những ký tự nào để 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 chuyển đến đầu dòng mới. Nhưng \r chỉ là trở về vận chuyển - nó quay trở lại phần đầ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 các 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 quầy bar dài hơn. (Bởi vì chúng ta đang sử dụng \ r, chúng tôi ở trên cùng một dòng) Ví dụ:

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

Những gì bạn cần phải nhớ để làm, là khi thực hiện, nếu sau đó 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 đã làm xong với thanh tiến trình, hãy chắc chắn in đủ khoảng trống để xóa nó khỏi dòng. Chẳng hạn như:

"done    |\n" 

Hy vọng điều đó sẽ hữu ích.

+0

Chắc chắn sẽ giúp bạn. Cảm ơn rất nhiều. –

+0

Đây có phải là nền tảng thực sự không? Nó có thể sẽ hoạt động tốt trên Windows và Linux, nhưng những gì về Mac? Tôi không có, vì vậy tôi không thể thử nó ... –

+1

@RaduMurzea OS X là một 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

2

Điều này có thể thực hiện được với thư viện Java Curses. This là những gì tôi đã tìm thấy. Tôi đã không sử dụng nó bản thân mình và tôi không biết nếu nó là nền tảng chéo.

+0

Các lời nguyền có thể hơi tốn kém cho việc sử dụng dễ dàng mà tôi cần, nhưng đó chắc chắn là một ca khúc. Cảm ơn. –

5

Ví dụ C# nhưng tôi giả định điều này giống nhau đối với System.out.print bằng Java. Hãy sửa lỗi nếu tôi sai.

Về cơ bản, bạn muốn ghi ký tự thoát \r vào đầu thư sẽ làm cho con trỏ trở về đầu dòng (Nguồn cấp dòng) mà không cần 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(); 

    } 
+0

Ví dụ hay, chắc chắn sẽ hữu ích. Cảm ơn. –

+0

Đẹp! Cảm ơn bạn. Làm việc như một người làm ăn. Dễ đọc. Lovely –

17

Tôi tìm thấy mã sau đây để hoạt động chính xác. Nó ghi byte vào bộ đệm đầu ra. Có lẽ các phương pháp sử dụng một nhà văn như phương pháp System.out.println() sẽ thay thế các lần xuất hiện của \r thành \n để khớp với dòng gốc của mục tiêu kết thúc (nếu không được định 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); 
     } 
    } 
} 
2

Tôi sử dụng thanh tiến trình "nảy" khi tôi cần trì hoãn 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"); 
} 
3

Đây là một phiên bản sửa đổi của các bên 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à trong chính:

loading("Calculating ..."); 
+0

Đây là một ví dụ tốt đẹp về Đa luồng! Rất hữu ích. – user7185318

2

Tôi đã tiến hành phần trăm tiến bộ để kiểm tra tệp tải xuống còn lại.

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

Nó cũng có thể được sử dụng cho mục đích công việc khác.

Test và ví dụ đầu ra

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

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

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

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

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

Thử nghiệm với vòng lặp for

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

Phương pháp này có thể dễ dàng chỉnh sửa:

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"); 
    } 
} 
0
while (true) { 
     System.out.write(("\r" + System.currentTimeMillis()).getBytes()); 
     Thread.sleep(1000); 
} 
0
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(); 
    } 
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 tôi: Tôi đã đặt nó cho một số trên 5%, 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

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

Simple thanh console tiến bộ. Quá trình viết thanh tiến trình hiện chạy trên một chuỗi khác.

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

Đối với phông chữ Consolas hoặc Andale Mono, hãy sử dụng ProgressBarStyle.ASCII (xem bên dưới) vì glyphs vẽ 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> 

Cách 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