Источник: Nuances of Programming
Курс SkillFactory Java-разработчик. Освойте backend-разработку и программирование на Java, Spring и основы DevOps. Соберите портфолио проектов и начните откликаться на вакансии уже после 7 месяцев обучения.
Как на стандартной консоли отображается индикатор выполнения, особенно в случаях, когда для загрузки пакетов используются менеджеры вроде npm? Рассмотрим решение.
Сначала создадим метод с именем printMsgWithProgressBar(), который содержит следующие параметры:
- String — выводимое сообщение;
- int — длина индикатора выполнения;
- long — интервал времени, ответственный за скорость показа анимации.
Поскольку мы будем вызывать метод из static main(), необходимо добавить модификатор static и к методу printMsgWithProgressBar(). В итоге, метод будет выглядеть так: public static void printMsgWithProgressBar(String message, int length, long timeInterval){ }.
Воспользуемся Java-классом StringBuilder для построения индикатора выполнения в качестве строки String. Возможно, у вас возникнет вопрос, каким образом прогресс-бар можно сформировать из строки. Но теперь мы прибегнем к магии, задействовав 2 символа Unicode.
- Символ U+2591 ░, чтобы показать незавершенный процесс выполнения.
- Символ 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);
}
}
Так прогресс-бар будет выглядеть, пока он не заполнен:
А так — когда анимация завершится:
Читайте также:
Перевод статьи Arunprasadh C: How to display a Progress Bar on the Standard Console using Java