Is there are easy way to implement a rolling percentage for a process in Java, to be displayed in the console? I have a percentage data type (double) I generated during a particular process, but can I force it to the console window and have it refresh, instead of just printing a new line for each new update to the percentage? I was thinking about pushing a cls and updating, because I'm working in a Windows environment, but I was hoping Java had some sort of built-in capability. All suggestions welcomed! Thanks!
Asked
Active
Viewed 4.1k times
9 Answers
56
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) {}
}
}

laalto
- 150,114
- 66
- 286
- 303
-
6
-
@David Johnstone: The example above works at least in traditional console windows. – laalto Jun 16 '09 at 13:26
-
@laalto: Yup, tried it in a normal console window and it worked for me. – Michael Jun 16 '09 at 19:05
-
1
-
Oh wow, sorry. I tried it in Eclipse also, and just assumed it scrolled down the entire page. Excellent! Thanks! – Monster Jun 18 '09 at 14:28
-
-
There's an age old Eclipse bug about carriage return. Many years have passed and it's still not fixed: https://bugs.eclipse.org/bugs/show_bug.cgi?id=76936 – anydoby Dec 19 '18 at 15:15
15
I use following code:
public static void main(String[] args) {
long total = 235;
long startTime = System.currentTimeMillis();
for (int i = 1; i <= total; i = i + 3) {
try {
Thread.sleep(50);
printProgress(startTime, total, i);
} catch (InterruptedException e) {
}
}
}
private static void printProgress(long startTime, long total, long current) {
long eta = current == 0 ? 0 :
(total - current) * (System.currentTimeMillis() - startTime) / current;
String etaHms = current == 0 ? "N/A" :
String.format("%02d:%02d:%02d", TimeUnit.MILLISECONDS.toHours(eta),
TimeUnit.MILLISECONDS.toMinutes(eta) % TimeUnit.HOURS.toMinutes(1),
TimeUnit.MILLISECONDS.toSeconds(eta) % TimeUnit.MINUTES.toSeconds(1));
StringBuilder string = new StringBuilder(140);
int percent = (int) (current * 100 / total);
string
.append('\r')
.append(String.join("", Collections.nCopies(percent == 0 ? 2 : 2 - (int) (Math.log10(percent)), " ")))
.append(String.format(" %d%% [", percent))
.append(String.join("", Collections.nCopies(percent, "=")))
.append('>')
.append(String.join("", Collections.nCopies(100 - percent, " ")))
.append(']')
.append(String.join("", Collections.nCopies(current == 0 ? (int) (Math.log10(total)) : (int) (Math.log10(total)) - (int) (Math.log10(current)), " ")))
.append(String.format(" %d/%d, ETA: %s", current, total, etaHms));
System.out.print(string);
}

Alexander Shuev
- 105
- 10

Mike Shauneu
- 3,201
- 19
- 21
-
2Wow! Thanks! For me working really good and better, than marked answer. – Samuel Tulach Feb 16 '17 at 16:43
-
Just a note for others, if you start your for loop with `i=0` then you may be getting an IllegalArgumentException from this code. Otherwise works a charm. – Sameen Mar 16 '17 at 14:23
-
1This didn't seem to work correctly for me. I copied it exactly, and instead of the progress bar staying on the same line, it printed new lines for each. – jeshbreadnan Jun 01 '17 at 14:03
-
-
For me, the CMD window was too small, hence it printed an output in a new line each time. When I made the window wider, it worked as expected. Note that `\r` deletes only the last line. – Aviran Katz Jun 13 '17 at 09:33
-
1
-
does not work. Java 8, Win 10 - prints the entire line at a time when the total time passes – Valeriy K. Feb 20 '20 at 10:49
4
I'm quite sure there is no way to change anything that the console has already printed because Java considers the console (standard out) to be a PrintStream.

David Johnstone
- 24,300
- 14
- 68
- 71
2
Don't know about anything built in to java itself, but you can use terminal control codes to do things like reposition the cursor. Some details here: http://www.termsys.demon.co.uk/vtansi.htm

Tom Jefferys
- 13,090
- 2
- 35
- 36
1
import java.util.Random;
public class ConsoleProgress {
private static String CURSOR_STRING = "0%.......10%.......20%.......30%.......40%.......50%.......60%.......70%.......80%.......90%.....100%";
private static final double MAX_STEP = CURSOR_STRING.length() - 1;
private double max;
private double step;
private double cursor;
private double lastCursor;
public static void main(String[] args) throws InterruptedException {
// ---------------------------------------------------------------------------------
int max = new Random().nextInt(400) + 1;
// ---------------------------------------------------------------------------------
// Example of use :
// ---------------------------------------------------------------------------------
ConsoleProgress progress = new ConsoleProgress("Progress (" + max + ") : ", max);
for (int i = 1; i <= max; i++, progress.nextProgress()) {
Thread.sleep(3L); // a task with no prints
}
}
public ConsoleProgress(String title, int maxCounts) {
cursor = 0.;
max = maxCounts;
step = MAX_STEP / max;
System.out.print(title);
printCursor();
nextProgress();
}
public void nextProgress() {
printCursor();
cursor += step;
}
private void printCursor() {
int intCursor = (int) Math.round(cursor) + 1;
System.out.print(CURSOR_STRING.substring((int) lastCursor, intCursor));
if (lastCursor != intCursor && intCursor == CURSOR_STRING.length())
System.out.println(); // final print
lastCursor = intCursor;
}
}

Elphara77
- 11
- 2
0
Clear the console by running the os specific command and then print the new percentage

Thejesh GN
- 1,108
- 2
- 14
- 28
0
Late for the party, but here's an answer:
public static String getSingleLineProgress(double progress) {
String progressOutput = "Progress: |";
String padding = Strings.padEnd("", (int) Math.ceil(progress / 5), '=');
progressOutput += Strings.padEnd(padding, 0, ' ') + df.format(progress) + "%|\r";
if (progress == 100.0D) {
progressOutput += "\n";
}
return progressOutput;
}
Remember to use System.out.print()
instead of System.out.println()

victorantunes
- 1,141
- 9
- 20