Skip to content
Advertisement

Print to a specific point in the terminal

I have a method that prints an upload progress like this:

36% [=================> ] 210,81 KB/s

To rewrite the line, I use the escape charachter 'r', which sets the “cursor” to the beginnig of the line.

Everything works as intended, but when i shrink down enough the terminal, it will write it on 2 lines, but when it prints again the line, only the second one is rewrited, and this is due to the escape character.

So what I was thnking about is creating a “checkpiont” in which rewrite the line, but I don’t know if that is possible and if yes how to do it.

The following is the method I’m talking about:

private static String progress(MediaHttpDownloader downloader, double deltaSeconds) throws IOException {
    int percent = (int) (downloader.getProgress() * 100);

    StringBuilder string = new StringBuilder(140)
            .append('r')
            .append(String.join("",
                    Collections.nCopies(percent == 0 ? 2 : 2 - (int) Math.log10(percent), " ")))
            .append(percent + "% [")
            .append(String.join("", Collections.nCopies(percent, "=")))
            .append('>')
            .append(String.join("", Collections.nCopies(100 - percent, " ")))
            .append("] "
                    + humanReadableByteCountSI(getSpeed(Main.CHUNK_SIZE, deltaSeconds))
                    + "/s ");

    return string.toString();
}

Any suggestions?


Edit: I tried using b and it seems to be in conflict with Gradle, so I will have to revert back to the prevoius solution, which still breaks when shrinking down the terminal.

Advertisement

Answer

I used to do the same thing as you, I have 2 suggestions.

1. You can use the b character for a backslash and reproduce everything.

2. You can try https://github.com/ctongfei/progressbar this api, its super simple!

Maven:

<dependency>
  <groupId>me.tongfei</groupId>
  <artifactId>progressbar</artifactId>
  <version>0.5.5</version>
</dependency>

Usage:

ProgressBar pb = new ProgressBar("Test", 100); // name, initial max
 // Use ProgressBar("Test", 100, ProgressBarStyle.ASCII) if you want ASCII output style
pb.start(); // the progress bar starts timing
// Or you could combine these two lines like this:
//   ProgressBar pb = new ProgressBar("Test", 100).start();
some loop {
  ...
  pb.step(); // step by 1
  pb.stepBy(n); // step by n
  ...
  pb.stepTo(n); // step directly to n
  ...
  pb.maxHint(n);
  // reset the max of this progress bar as n. This may be useful when the program
  // gets new information about the current progress.
  // Can set n to be less than zero: this means that this progress bar would become
  // indefinite: the max would be unknown.
  ...
  pb.setExtraMessage("Reading..."); // Set extra message to display at the end of the bar
}
pb.stop() // stops the progress bar
User contributions licensed under: CC BY-SA
2 People found this is helpful
Advertisement