Command Line Progress Bar in Java

Command line progress bar in Java

I have implemented this sort of thing before. Its not so much about java, but what characters to send to the console.

The key is the difference between \n and \r.
\n goes to the start of a new line. But \r is just carriage return - it goes back to the start of the same line.

So the thing to do is to print your progress bar, for example, by printing the string

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

On the next tick of the progress bar, overwrite the same line with a longer bar. (because we are using \r, we stay on the same line) For example:

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

What you have to remember to do, is when done, if you then just print

"done!\n"

You may still have some garbage from the progress bar on the line. So after you are done with the progress bar, be sure to print enough whitespace to remove it from the line. Such as:

"done             |\n"

How to create a threaded console progress bar in Java?

Why do you need a multithreaded application when it is just one task you are trying to achieve?

Nonetheless, to achieve what you want I suggest moving your execution entirely into either the thread class or into the main class.

If the main application is going to run something else, then ideally you'd put the execution in the thread class. However here I've put the execution into the main class. It could also just as easily go in the thread class.

As an example, I've edited run() in ProgressThread to just be this,

public void run()
{
while( terminated )
{
}
}

And I edited main in ConsoleProgressBar to this,

public static void main(String[] args)
{
ArrayList<Integer> test = new ArrayList<>();
ConsoleProgressBar bar = new ConsoleProgressBar(10, 50);

bar.start();

for (int i = 0; i <= 10; i++)
{
int sum = i + 5;

test.add(sum);

bar.refreshProgressBar();
System.out.format( "%s", bar.getCurrent() );
bar.step();
bar.sleep( 1000 );
}

bar.stop();
}

Note that I added the methods sleep( int n ) and refreshProgressBar() to bar so I can call the thread methods, similar to what you did with bar.start() and bar.stop().

To be clear, in ProgressThread I changed refreshProgressBar to public just for the sake of the example and added the following,

void sleep( int n )
{
try
{
Thread.sleep( n );
}
catch( InterruptedException ie )
{
ie.printStackTrace();
}
}

and the following to ConsoleProgressBar,

private void sleep( int n )
{
target.sleep( n );
}

private void refreshProgressBar()
{
target.refreshProgressBar();

}

The output (each line printing at one second intervals) is,

[>                                                 ] 0%  0
[=====> ] 10% 1
[==========> ] 20% 2
[===============> ] 30% 3
[====================> ] 40% 4
[=========================> ] 50% 5
[==============================> ] 60% 6
[===================================> ] 70% 7
[========================================> ] 80% 8
[=============================================> ] 90% 9
[==================================================] 100% 10

Not sure if this is what you are looking for but I suggest putting the execution into one place.

Command-line Progress bar with occupied indicator

I think I solved this, inspired by @Stefan Lindenberg and @nafas. I merged two methods into one, the busy indicator spins continuously as the last character of the progress bar, which I update with a progress:

class ProgressBar extends Thread {

private static final String anim = "|/-\\";
private boolean showProgress;
double progressPercentage;
private final int barLength;

public ProgressBar(int barLength) {
this.barLength = barLength;
this.showProgress = true;
this.progressPercentage = 0;
}

public void run() {

int i = 0;

while (showProgress) {

String progress = "\r";
int column = (int) (progressPercentage * barLength);
for (int j = 0; j <= column; j++) {
progress += ("*");
}

System.out.print(progress + anim.charAt(i++ % anim.length()));

try {

Thread.sleep(10);

} catch (Exception e) {
// do nothing
}// END: try-catch

}// END: while

}// END: run

public void setShowProgress(boolean showProgress) {
this.showProgress = showProgress;
}

public void setProgressPercentage(double progressPercentage) {
this.progressPercentage = progressPercentage;
}
}// END: class

and this is then used like this:

        for (int i = 0; i <= jobLength; i++) {

Thread.sleep(100);

double progress = (stepSize * i) / barLength;
progressBar.setProgressPercentage(progress);

}

Looks ok.

Console based progress in Java

You can print a carriage return \r to put the cursor back to the beginning of line.

Example:

public class ProgressDemo {
static void updateProgress(double progressPercentage) {
final int width = 50; // progress bar width in chars

System.out.print("\r[");
int i = 0;
for (; i <= (int)(progressPercentage*width); i++) {
System.out.print(".");
}
for (; i < width; i++) {
System.out.print(" ");
}
System.out.print("]");
}

public static void main(String[] args) {
try {
for (double progressPercentage = 0.0; progressPercentage < 1.0; progressPercentage += 0.01) {
updateProgress(progressPercentage);
Thread.sleep(20);
}
} catch (InterruptedException e) {}
}
}

How to make a progress bar in Java console application?

You need to write a piece of code that produces a ten-character String starting in #s and ending in spaces. Pass this method a number from 0 to 100. The method should divide the number by ten, rounding the result up. This will give you the number of # characters in the ten-character bar:

int numPounds = (pct + 9) / 10;

Make a loop that appends '#' numPounds times, and then appends ' ' until the length of the string is ten. Print the result between [ ... ] characters to complete the exercise.

private static final StringBuilder res = new StringBuilder();;

static String progress(int pct) {
res.delete(0, res.length());
int numPounds = (pct + 9) / 10;
for (int i = 0 ; i != numPounds ; i++) {
res.append('#');
}
while (res.length() != 10) {
res.append(' ');
}
return res.toString();
}

public static void main (String[] args) throws java.lang.Exception
{
for (int i = 0 ; i <= 100 ; i++) {
Thread.sleep(10);
System.out.print(String.format("[%s]%d%%\r", progress(i), i));
}
}

Non-deterministic progress bar on java command line

Here an example to show a rotating progress bar and the traditional style :

import java.io.*;
public class ConsoleProgressBar {
public static void main(String[] argv) throws Exception{
System.out.println("Rotating progress bar");
ProgressBarRotating pb1 = new ProgressBarRotating();
pb1.start();
int j = 0;
for (int x =0 ; x < 2000 ; x++){
// do some activities
FileWriter fw = new FileWriter("c:/temp/x.out", true);
fw.write(j++);
fw.close();
}
pb1.showProgress = false;
System.out.println("\nDone " + j);

System.out.println("Traditional progress bar");
ProgressBarTraditional pb2 = new ProgressBarTraditional();
pb2.start();
j = 0;
for (int x =0 ; x < 2000 ; x++){
// do some activities
FileWriter fw = new FileWriter("c:/temp/x.out", true);
fw.write(j++);
fw.close();
}
pb2.showProgress = false;
System.out.println("\nDone " + j);
}
}

class ProgressBarRotating extends Thread {
boolean showProgress = true;
public void run() {
String anim= "|/-\\";
int x = 0;
while (showProgress) {
System.out.print("\r Processing " + anim.charAt(x++ % anim.length()));
try { Thread.sleep(100); }
catch (Exception e) {};
}
}
}

class ProgressBarTraditional extends Thread {
boolean showProgress = true;
public void run() {
String anim = "=====================";
int x = 0;
while (showProgress) {
System.out.print("\r Processing "
+ anim.substring(0, x++ % anim.length())
+ " ");
try { Thread.sleep(100); }
catch (Exception e) {};
}
}
}

Use java to draw a progress bar in the console

I'm using Mac with Java 8. This demo works for me. I didn't test it on Windows :(

NOTE: if you run the code in your IDE(eg. IntelliJ, Eclipse, etc.), it may doesn't work. The right place to test it is in the terminal.

Steps to run

  1. open the folder where this code located in your terminal;
  2. compile the code javac Demo.java
  3. run it java Demo

    import java.io.IOException;
    import java.util.concurrent.TimeUnit;

    public class Demo {
    public static void main(String[] args) throws InterruptedException, IOException {

    int i = 0;
    int j;

    while (i <= 100) {
    System.out.print("\033[H\033[2J");
    j = 0;
    for (j = 0; j < i; j++) {
    System.out.print('■');
    }
    for (; j <= 100; j++) System.out.print(' ');
    System.out.print(i + "%");
    TimeUnit.SECONDS.sleep(1);
    i += 2;
    }
    }
    }

PS.

In the code above, you might be confused with this line: System.out.print("\033[H\033[2J");

  • 'H' means move to top of the screen
  • '2J' means "clear entire screen"

Here is the detailed explanation



Related Topics



Leave a reply



Submit