У меня есть программа Java, работающая в режиме командной строки. Я хотел бы отобразить индикатор выполнения, показывающий процент выполненной работы. Тот же индикатор выполнения, что и при использовании wget в unix. Это возможно?
У меня есть программа Java, работающая в режиме командной строки. Я хотел бы отобразить индикатор выполнения, показывающий процент выполненной работы. Тот же индикатор выполнения, что и при использовании wget в unix. Это возможно?
Ответы:
Я реализовывал подобные вещи раньше. Дело не столько в java, сколько в том, какие символы отправлять в консоль.
Ключевым моментом является разница между \n
и \r
.
\n
переходит в начало новой строки. Но \r
это просто возврат каретки - он возвращается в начало той же строки.
Поэтому нужно распечатать индикатор выполнения, например, напечатав строку
"|======== |\r"
На следующем тике индикатора выполнения замените ту же строку более длинной полосой. (поскольку мы используем \ r, мы остаемся на той же строке) Например:
"|========= |\r"
Что вы должны сделать, это когда вы закончите, просто напечатайте
"done!\n"
У вас все еще может быть мусор от индикатора выполнения на строке. Поэтому после того, как вы закончите с индикатором выполнения, обязательно напечатайте достаточно пробелов, чтобы удалить его из строки. Такие как:
"done |\n"
Надеюсь, это поможет.
Есть https://github.com/ctongfei/progressbar , Лицензия: MIT
Простой индикатор выполнения консоли. Запись индикатора выполнения теперь выполняется в другом потоке.
Menlo, 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
step()
вызовами)? Ваша библиотека работает асинхронно, что позволяет обновлять часы? Что, если моя библиотека работает несколько дней? Использует ли он /r
стратегию? Приведет ли это к выходу в несколько сотен мегабайт?
Я обнаружил, что следующий код работает правильно. Он записывает байты в выходной буфер. Возможно, эти методы, использующие писатель, например 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);
}
}
}
Я сделал процентный прогресс, чтобы проверить оставшийся файл загрузки.
Я периодически вызываю этот метод при загрузке файла, чтобы проверить общий и оставшийся размер файла и представить его в %
.
Его также можно использовать для других целей.
Пример тестирования и вывода
progressPercentage(0, 1000);
[----------] 0%
progressPercentage(10, 100);
[*---------] 10%
progressPercentage(500000, 1000000);
[*****-----] 50%
progressPercentage(90, 100);
[*********-] 90%
progressPercentage(1000, 1000);
[**********] 100%
Тест с помощью цикла for
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");
}
}
Пример C #, но я предполагаю, что это то же самое для System.out.print
Java. Не стесняйтесь поправлять меня, если я ошибаюсь.
По сути, вы хотите записать \r
escape-символ в начало вашего сообщения, что приведет к тому, что курсор вернется в начало строки (Line Feed) без перехода к следующей строке.
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();
}
Немного переработан и обновлен метод @ maytham-ɯɐɥʇʎɐɯ. Теперь он поддерживает произвольный размер индикатора выполнения:
public static void progressPercentage(int done, int total) {
int size = 5;
String iconLeftBoundary = "[";
String iconDone = "=";
String iconRemain = ".";
String iconRightBoundary = "]";
if (done > total) {
throw new IllegalArgumentException();
}
int donePercents = (100 * done) / total;
int doneLength = size * donePercents / 100;
StringBuilder bar = new StringBuilder(iconLeftBoundary);
for (int i = 0; i < size; i++) {
if (i < doneLength) {
bar.append(iconDone);
} else {
bar.append(iconRemain);
}
}
bar.append(iconRightBoundary);
System.out.print("\r" + bar + " " + donePercents + "%");
if (done == total) {
System.out.print("\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();
}
... и в основном:
loading("Calculating ...");
Я использую «подпрыгивающий» индикатор выполнения, когда мне нужно отложить инструмент, чтобы предотвратить состояние гонки.
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");
}
Я недавно столкнулся с той же проблемой, вы можете проверить мой код: я установил его для одного # на 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();
}
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();
}
Я отредактировал код Эоина Кэмпбелла на java и добавил отформатированный прогресс в процентах.
public static String progressBar(int currentValue, int maxValue) {
int progressBarLength = 33; //
if (progressBarLength < 9 || progressBarLength % 2 == 0) {
throw new ArithmeticException("formattedPercent.length() = 9! + even number of chars (one for each side)");
}
int currentProgressBarIndex = (int) Math.ceil(((double) progressBarLength / maxValue) * currentValue);
String formattedPercent = String.format(" %5.1f %% ", (100 * currentProgressBarIndex) / (double) progressBarLength);
int percentStartIndex = ((progressBarLength - formattedPercent.length()) / 2);
StringBuilder sb = new StringBuilder();
sb.append("[");
for (int progressBarIndex = 0; progressBarIndex < progressBarLength; progressBarIndex++) {
if (progressBarIndex <= percentStartIndex - 1
|| progressBarIndex >= percentStartIndex + formattedPercent.length()) {
sb.append(currentProgressBarIndex <= progressBarIndex ? " " : "=");
} else if (progressBarIndex == percentStartIndex) {
sb.append(formattedPercent);
}
}
sb.append("]");
return sb.toString();
}
int max = 22;
System.out.println("Generating report...");
for (int i = 0; i <= max; i++) {
Thread.sleep(100);
System.out.print(String.format("\r%s", progressBar(i, max)));
}
System.out.println("\nSuccessfully saved 32128 bytes");
И вывод:
Generating report...
[======== 24.2 % ]
[============ 45.5 % ]
[============ 78.8 % ===== ]
[============ 87.9 % ======== ]
[============ 100.0 % ============]
Successfully saved 32128 bytes
public class ProgressBar
{
private int max;
public ProgressBar(int max0) {
max = max0;
update(0);
}
public void update(int perc) {
String toPrint = "|";
for(int i = 0; i < max; i++) {
if(i <= (perc + 1))
toPrint += "=";
else
toPrint += " ";
}
if(perc >= max)
Console.print("\r");
else
Console.print(toPrint + "|\r");
}
}
public class Main {
public static void main(String[] args) throws Exception {
System.out.println("Loading : ");
int count =1;
for(int j=1;j<150;j++){
System.out.print("\r");
if(count==1){
System.out.print("/");
count++;
}
else if(count==2){
System.out.print("|");
count++;
}
else if(count==3){
System.out.print("-");
count++;
}
else if(count==4){
System.out.print("\\");
count++;
}
else if(count==5){
System.out.print("|");
count++;
}
else
count = 1;
Thread.sleep(200);
}
}
}
static String progressBar(int progressBarSize, long currentPosition, long startPositoin, long finishPosition) {
String bar = "";
int nPositions = progressBarSize;
char pb = '░';
char stat = '█';
for (int p = 0; p < nPositions; p++) {
bar += pb;
}
int ststus = (int) (100 * (currentPosition - startPositoin) / (finishPosition - startPositoin));
int move = (nPositions * ststus) / 100;
return "[" + bar.substring(0, move).replace(pb, stat) + ststus + "%" + bar.substring(move, bar.length()) + "]";
}