2009-05-12 2 views
87

У меня есть программа Java, работающая в режиме командной строки. Я хотел бы отобразить индикатор выполнения, показывающий процент выполненной работы. Такой же индикатор прогресса, который вы увидите с помощью wget под unix. Возможно ли это?Строка выполнения командной строки в Java

+0

Я не знаю ответа на Ваш вопрос, но вы могли бы начать с проверки библиотек, упомянутых в этом вопросе : http://stackoverflow.com/questions/435740/are-there-good-java-libraries-that-facilitate-building-command-line-applications – Jonik

+0

Спасибо. В цитированных библиотеках больше говорится о синтаксическом анализе аргументов командной строки, а не отображении в консоли. Но спасибо в любом случае. –

+6

Это по теме. OP спрашивает, если это возможно, а не для рекомендации библиотеки (по крайней мере, в текущем редактировании) –

ответ

132

Я уже реализовал этот вид вещей. Это не столько о Java, сколько о том, какие персонажи отправлять на консоль.

Ключ является разницей между \n и \r. \n переходит в начало новой линии. Но \r всего лишь возврат каретки - он возвращается к началу той же линии.

Так что нужно сделать, чтобы напечатать ваш прогресс бар, например, путем печати Строки

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

На следующем тике индикатора выполнения, перезаписать ту же линию с более баром. (Потому что мы используем \ г, мы остаемся на той же линии) Например:

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

То, что вы должны помнить, чтобы сделать, это когда сделано, если вы потом просто распечатать

"done!\n" 

Вы может по-прежнему иметь мусор из индикатора выполнения на линии. Поэтому после того, как вы закончите работу с индикатором выполнения, обязательно напечатайте достаточно пробелов, чтобы удалить его из строки. Такие как:

"done    |\n" 

Надеюсь, что это поможет.

+0

Несомненно помогает. Большое спасибо. –

+0

Действительно ли это кросс-платформенный? Вероятно, он будет нормально работать в Windows и Linux, но как насчет Mac? У меня его нет, поэтому я не могу попробовать ... –

+1

@RaduMurzea OS X - это ОС NIX, поэтому, если она работает в Linux, она будет работать на OS X (это не так для всех, но это правда). – bfontaine

2

Это возможно с помощью библиотеки Java Curses. This - это то, что я нашел. Я не использовал его сам, и я не знаю, является ли это кросс-платформенным.

+0

Проклятия могут быть немного накладными расходами для удобного использования, в котором я нуждаюсь, но это наверняка трек. Благодарю. –

5

C# Пример, но я предполагаю, что это то же самое для System.out.print в Java. Не стесняйтесь исправлять меня, если я ошибаюсь.

В принципе, вы хотите записать escape-символ \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(); 

    } 
+0

Приятный пример, обязательно будет полезен. Благодарю. –

+0

Красивая! Спасибо. Работает как заклинатель. Легко читается. Lovely –

17

Я нашел следующий код для правильной работы. Он записывает байты в выходной буфер. Возможно, что методы с использованием писателя, такие как метод System.out.println(), заменяют вхождения \r на \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); 
     } 
    } 
} 
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"); 
} 
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 ..."); 
+0

Это хороший пример многопоточности! Очень полезно. – user7185318

2

Я проделал определенный процентный прогресс, чтобы проверить оставшийся файл загрузки.

Я периодически вызываю метод в своем файле, чтобы проверить общий размер файла и оставить его и оставить в %.

Его можно использовать и для других целей.

Тест и выход Пример

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

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

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

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

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

Тест с петлей для

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

Я недавно столкнулся с такой же проблемой, вы можете проверить мой код: Я установил его для одного # на 5%, который вы можете изменить позже.

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, Лицензия: MIT

Простой прогресс консоли бар. Запись строки выполнения теперь выполняется в другом потоке.

Менло, 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