Explain Codes LogoExplain Codes Logo

Command line progress bar in Java

java
prompt-engineering
performance
best-practices
Anton ShumikhinbyAnton Shumikhin·Aug 28, 2024
TLDR

For rapid development, the immediate solution is a straightforward method updateProgressBar(). The method showcases a dynamic progress bar illustrating the ratio of tasks completed to the total tasks. The display precision is regulated by String.format. It promptly provides visual feedback to the user.

public static void updateProgressBar(int done, int total) { String format = "\r%3d%% %s %c"; String icon = "="; // We're laying down some solid tracks! int width = 50; // Width scaling of progress bar int progress = (done * width) / total; String bar = new String(new char[progress]).replace('\0', icon.charAt(0)) + new String(new char[width - progress]).replace('\0', ' '); System.out.printf(format, (done * 100) / total, bar, '|'); } // Within a loop, the task is simulating progress for (int i = 0; i <= total; i++) { updateProgressBar(i, total); Thread.sleep(100); // zzzZZZ... replace with actual task processing }

Key to understand:

  • \r: Cursor to line start, so no talk of new lines.
  • %3d%%: Display an integer followed closely by a literal %.
  • Progress calculation: (done * width) / total is perfectly scaled for the bar.
  • Thread.sleep: This is your task's placeholder duration. Please kindly replace with genuine processing

Practical Enhancements

White Space: Your Eraser

Once your progress bar reaches full completion, the display line can sometimes end with extraneous characters. To get rid of them, simply print a line full of white spaces followed by a newline '\n' character right after your progress bar completes.

System.out.print("\r" + new String(new char[width]).replace('\0', ' ') + "\n");

With this addition, your command line looks neat, companionship intact!

StringBuilder: The Performance Booster

In a scenario where your updates are drastically frequent, StringBuilder provides a more efficient string manipulation mechanism than traditional concatenation. A good practice is to use StringBuilder to construct your progress bar's visual representation.

StringBuilder barBuilder = new StringBuilder(width); for (int i = 0; i < progress; i++) { barBuilder.append(icon); } for (int i = progress; i < width; i++) { barBuilder.append(' '); } System.out.printf(format, (done * 100) / total, barBuilder.toString(), '|');

Graceful Interruptions

There might be scenarios where your long-running tasks may need interruptions. The progress bar process should respectfully handle this situation.

try { for (int i = 0; i <= total; i++) { if (Thread.interrupted()) { // Clean up code if thread gets interrupted. break; } updateProgressBar(i, total); Thread.sleep(100); // This process ends without snoring! } } catch (InterruptedException ex) { Thread.currentThread().interrupt(); // Reset and get back on track // Optional: Inform the user about the interruption System.out.println("Alright, calm down! Progress interrupted!"); }

Font Shout-out

Monospaced fonts help your progress bar maintain its visual integrity across different environments which significantly enhances the readability. Fonts worth considering are Menlo, Fira Mono, Source Code Pro, or SF Mono.

Expanding the Scope

I, Library

If off-the-rack solutions serve your purpose better, ProgressBar can provide a one-stop, customized solution. Allowing styles and options for ASCII-based bars that you can pair with Consolas and Andale Mono fonts.

Be the update in Real-Time

Further enhancement can indeed come from real-time progress updates which considerably improves the user experience, particularly if you have constant dynamic changes that the user can follow.