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
- open the folder where this code located in your terminal;
- compile the code
javac Demo.java
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
How to Merge Documents Correctly
When Does Java's Thread.Sleep Throw Interruptedexception
Eclipse/Maven Error: "No Compiler Is Provided in This Environment"
Sonar Violation: Security - Array Is Stored Directly
How to Get a Random Line of a Text File in Java
What Does Super.Paintcomponent(G) Do
Javafx: "Toolkit" Not Initialized When Trying to Play an Mp3 File Through Mediaplayer Class
Reverse Java Graphics2D Scaled and Rotated Coordinates
Difference Between Paint() and Paintcomponent()
Java Two Varargs in One Method
Can't Rid of 'T' in Localdatetime
In Java, How to Call a Base Class's Method from the Overriding Method in a Derived Class
How to Hide Cursor in a Swing Application
How to Create a New Packaging Type for Maven
Invalid Signature File Digest for Manifest Main Attributes Exception While Trying to Run Jar File
Cannot Instantiate the Type List<Product>
How Do Determine If an Object Is Locked (Synchronized) So Not to Block in Java