Как отобразить индикатор выполнения на стандартной консоли с помощью Java

Как на стандартной консоли отображается индикатор выполнения, особенно в случаях, когда для загрузки пакетов используются менеджеры вроде npm? Рассмотрим решение.

Сначала создадим метод с именем printMsgWithProgressBar(), который содержит следующие параметры:

  • String  —  выводимое сообщение;
  • int  —  длина индикатора выполнения;
  • long  —  интервал времени, ответственный за скорость показа анимации.

Поскольку мы будем вызывать метод из static main(), необходимо добавить модификатор static и к методу printMsgWithProgressBar(). В итоге, метод будет выглядеть так: public static void printMsgWithProgressBar(String message, int length, long timeInterval){ }.

Воспользуемся Java-классом StringBuilder для построения индикатора выполнения в качестве строки String. Возможно, у вас возникнет вопрос, каким образом прогресс-бар можно сформировать из строки. Но теперь мы прибегнем к магии, задействовав 2 символа Unicode.

  1. Символ U+2591 ░, чтобы показать незавершенный процесс выполнения.
  2. Символ U+2588 █  —  для завершенного процесса.

Обратите внимание: эти символы могут не поддерживаться в консолях, если те не поддерживают символы Unicode в целом. В таком случае для отображения индикатора выполнения можно использовать другие символы, такие как = и   .

Для создания прогресс-бара возьмем StringBuilder. Следует использовать фабричный метод generate() из Java Stream API для создания индикатора выполнения с Unicode-символом незавершенности. Для этой цели можно также применить простой цикл. На этом этапе код должен выглядеть так:

public static void printMsgWithProgressBar(String message, int length, long timeInterval)
{
char incomplete = '░'; // U+2591 Unicode Character
char complete = '█'; // U+2588 Unicode Character StringBuilder builder = new StringBuilder();
Stream.generate(() -> incomplete).limit(length).forEach(builder::append);
}

Прежде чем показывать индикатор выполнения, нужно задать выводимое сообщение. Объявим цикл for с итератором int от 0 до length-1. Внутри цикла заменим i-тый символ builder на полный блок символов Unicode и выведем на печать индикатор выполнения. Теперь код должен выглядеть следующим образом:

public static void printMsgWithProgressBar(String message, int length, long timeInterval)    
{
char incomplete = '░'; // U+2591 Unicode Character
char complete = '█'; // U+2588 Unicode Character StringBuilder builder = new StringBuilder();
Stream.generate(() -> incomplete).limit(length).forEach(builder::append);
for(int i = 0; i < length; i++)
{
builder.replace(i,i+1,String.valueOf(complete));
System.out.print(builder);
}
}

Если выполнять этот метод из main(), он не будет выводить индикатор. Вместо этого String будет выводиться в каждом цикле заново, иногда даже с переносом на следующую строку. Как же выводить обновленный индикатор выполнения в одной и той же строке на каждой итерации?

Мы будем использовать возврат каретки \r, который заставляет консоль перемещать курсор в начало строки после того, как завершится печать. Перед выводом на печать нам необходимо добавить символ \r в builder. Теперь код выглядит так:

public static void printMsgWithProgressBar(String message, int length, long timeInterval)    
{
char incomplete = '░'; // U+2591 Unicode Character
char complete = '█'; // U+2588 Unicode Character StringBuilder builder = new StringBuilder();
Stream.generate(() -> incomplete).limit(length).forEach(builder::append);
for(int i = 0; i < length; i++)
{
builder.replace(i,i+1,String.valueOf(complete));
String progressBar = "\r" + builder;
System.out.print(progressBar);
}
}

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

Чтобы добавить эту задержку, воспользуемся величиной timeInterval в качестве аргумента метода. Выполнение кода будет останавливаться через регулярные промежутки времени с помощью метода Thread.sleep() с временным интервалом timeInterval в качестве параметра.

Вот и все! Теперь при запуске кода вы получите анимированный индикатор выполнения на консоли. Вот весь код целиком:

import java.util.stream.Stream;

public class Main
{
public static void printMsgWithProgressBar(String message, int length, long timeInterval)
{
char incomplete = '░'; // U+2591 Unicode Character
char complete = '█'; // U+2588 Unicode Character
StringBuilder builder = new StringBuilder();
Stream.generate(() -> incomplete).limit(length).forEach(builder::append);
System.out.println(message);
for(int i = 0; i < length; i++)
{
builder.replace(i,i+1,String.valueOf(complete));
String progressBar = "\r"+builder;
System.out.print(progressBar);
try
{
Thread.sleep(timeInterval);
}
catch (InterruptedException ignored)
{

}
}
}
public static void main(String[] args)
{
printMsgWithProgressBar("Loading", 25, 60);
}
}

Так прогресс-бар будет выглядеть, пока он не заполнен:

А так  —  когда анимация завершится:

Читайте также:

Читайте нас в TelegramVK и Дзен


Перевод статьи Arunprasadh C: How to display a Progress Bar on the Standard Console using Java

Предыдущая статьяЧто такое Flutter и зачем его изучать?
Следующая статьяИстория создания одного бессерверного приложения рассылки с открытым ПО