Как на стандартной консоли отображается индикатор выполнения, особенно в случаях, когда для загрузки пакетов используются менеджеры вроде 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);
}
}
Так прогресс-бар будет выглядеть, пока он не заполнен:
А так — когда анимация завершится:
Читайте также:
- Как читать CSV-файлы на Java с помощью Open CSV
- Реализация структурированной конкурентности в Java и Kotlin
- Ссылки на методы в Java
Читайте нас в Telegram, VK и Дзен
Перевод статьи Arunprasadh C: How to display a Progress Bar on the Standard Console using Java