Periklis Ntanasis:
Master's Touch

fade out

Java: A simple and neat cli Progress Bar

Back on June c00kiemon5ter wrote a cli progress bar in java. As it seems it isn’t something difficult but I find it pretty usefull and worth to be mentioned. The progress bar was originally written as part of F.I.C.

Here is how it looks like:

Progress Bar Demo

Usage

Let’s see how you can use it in your own project. The ProgressBar Class is the following one:

/**
 * Ascii progress meter. On completion this will reset itself,
 * so it can be reused
 * <br /><br />
 * 100% ################################################## |
 */
public class ProgressBar {
    private StringBuilder progress;

    /**
     * initialize progress bar properties.
     */
    public ProgressBar() {
        init();
    }

    /**
     * called whenever the progress bar needs to be updated.
     * that is whenever progress was made.
     *
     * @param done an int representing the work done so far
     * @param total an int representing the total work
     */
    public void update(int done, int total) {
        char[] workchars = {'|', '/', '-', '\\'};
        String format = "\r%3d%% %s %c";

        int percent = (++done * 100) / total;
        int extrachars = (percent / 2) - this.progress.length();

        while (extrachars-- > 0) {
            progress.append('#');
        }

        System.out.printf(format, percent, progress,
         workchars[done % workchars.length]);

        if (done == total) {
            System.out.flush();
            System.out.println();
            init();
        }
    }

    private void init() {
        this.progress = new StringBuilder(60);
    }
}

Just copy it in a ProgressBar.java file or something in your desired package (and add the appropriate package name).

Then you have to initialize it and call manually the update method. The update method takes the done work units so far and the total work units.

Here is an example:

package progressbardemo;

public class ProgressBarDemo {

    public static void main(String[] args) {
        ProgressBar bar = new ProgressBar();

        System.out.println("Process Starts Now!");

        bar.update(0, 1000);
        for(int i=0;i<1000;i++) {
                        // do something!
            for(int j=0;j<10000000;j++)
                for(int p=0;p<10000000;p++);
            // update the progress bar
            bar.update(i, 1000);
        }
        System.out.println("Process Completed!");
    }
}

As you can see the total work units can be changed during the program execution. So, if we have a program that copies files and has copied X of Y we use bar.update(X,Y); but if suddenly we have to copy K more files then we use bar.update(X',Y+K); , on the fly.

Warning The Progress Bar is meaningful only when the user has to wait. If the process terminates quickly it is meaningless and furthermore the symbols are drawn way too fast and not smoothly!

You can find the Progress Bar original code here. You can also check the F.I.C. project to see how it was used there.

How it works

Let’s have a look in the code and understand how the magic works.

First of all c00kiemon5ter creates a StringBuilder object of 60 characters long. This is obviously the progress bar!

So let’s see the update method. I’ll introduce it again with extra comments that explain what’s happening.

/**
 * called whenever the progress bar needs to be updated.
 * that is whenever progress was made.
 *
 * @param done an int representing the work done so far
 * @param total an int representing the total work
 */
 public void update(int done, int total) {
    // contains the characters that create the spinning wait symbol
    char[] workchars = {'|', '/', '-', '\\'};
    /**
     * it is the progress bar format.
     * let's have a closer look:
     * - \r is the carriage return, in other words it moves
     *   the "cursor" to the first position on the same line
     * - %3d is a 3 digit decimal integer
     * - %% is the literal % character
     * - %s is a string, particularly the "###...#" symbols
     * - %c is a character, particularly the spinning wait symbol
     */
    String format = "\r%3d%% %s %c";

    // calculates how much work units per cent have been completed
    int percent = (++done * 100) / total;
    // total number of # to be appended
    int extrachars = (percent / 2) - this.progress.length();

    // append the # to the progress bar
    while (extrachars-- > 0) {
        progress.append('#');
    }

    // updates/redraws the progress bar
    System.out.printf(format, percent,
    progress, workchars[done % workchars.length]);

    /**
     * if the work have been completed it forces the output
     * to be written, changes line and resets itself so it
     * can be reused.
     */
    if (done == total) {
        System.out.flush();
        System.out.println();
        init();
    }
 }

That was c00kiemon5ter’s simple but pretty cli progress bar. Thank you dude! :)

Comments

fade out