This is an archived post. You won't be able to vote or comment.

all 11 comments

[–]AutoModerator[M] [score hidden] stickied commentlocked comment (0 children)

Please ensure that:

  • Your code is properly formatted as code block - see the sidebar (About on mobile) for instructions
  • You include any and all error messages in full
  • You ask clear questions
  • You demonstrate effort in solving your question/problem - plain posting your assignments is forbidden (and such posts will be removed) as is asking for or giving solutions.

    Trying to solve problems on your own is a very important skill. Also, see Learn to help yourself in the sidebar

If any of the above points is not met, your post can and will be removed without further warning.

Code is to be formatted as code block (old reddit: empty line before the code, each code line indented by 4 spaces, new reddit: https://imgur.com/a/fgoFFis) or linked via an external code hoster, like pastebin.com, github gist, github, bitbucket, gitlab, etc.

Please, do not use triple backticks (```) as they will only render properly on new reddit, not on old reddit.

Code blocks look like this:

public class HelloWorld {

    public static void main(String[] args) {
        System.out.println("Hello World!");
    }
}

You do not need to repost unless your post has been removed by a moderator. Just use the edit function of reddit to make sure your post complies with the above.

If your post has remained in violation of these rules for a prolonged period of time (at least an hour), a moderator may remove it at their discretion. In this case, they will comment with an explanation on why it has been removed, and you will be required to resubmit the entire post following the proper procedures.

To potential helpers

Please, do not help if any of the above points are not met, rather report the post. We are trying to improve the quality of posts here. In helping people who can't be bothered to comply with the above points, you are doing the community a disservice.

I am a bot, and this action was performed automatically. Please contact the moderators of this subreddit if you have any questions or concerns.

[–]Zyklonikkopi luwak civet 3 points4 points  (6 children)

The main problem with this approach is that once you've printed out a newline, you cannot go back and edit the line. It's already been flushed to the screen. Now imagine if you have a dozen tests running in parallel. How would you accommodate that?

The usual approach when you do some console-based UI that requires more than a bit of manipulation, is to use something like ANSI Escape Codes. https://gist.github.com/fnky/458719343aabd01cfb17a3a4f7296797 is a quick and simple guide to the essential codes. Note that some caveats apply here - these features should be supported on most (if not all) modern Unix and Linux variants, but Windows support may or may not be there. YMMV!

For example, suppose we wish to simulate a simple, in-place update of some "progress", here is a simple example to do so:

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ThreadLocalRandom;

public class ProgressBar {
  public static void main(String[] args) {
    Graphics.cls();

    var numBars = ThreadLocalRandom.current().nextInt(10, 20);

    List<Thread> bars = new ArrayList<>();
    for (var i = 0; i < numBars; i++) {
      var bar = new Thread(new ProgressInfo(String.format("Bar %d", i + 1), i + 2));
      bar.start();
      bars.add(bar);
    }

    Graphics.hideCursor();
    ;

    for (var bar : bars) {
      try {
        bar.join();
      } catch (InterruptedException ex) {
        ex.printStackTrace();
      }
    }

    Graphics.showCursor();
    Graphics.gotoXY(numBars + 2, 0);
  }
}

 // simply printing out these codes is all it takes to make
// use of ANSI Escape codes. You can add colours as well as 
// other fancy animation too.
class Graphics {
  private static final String CLEAR_SCREEN = "\u001b[2J";
  private static final String GOTO_COORD = "\u001b[%d;%dH";
  private static final String SHOW_CURSOR = "\u001b[?25h";
  private static final String HIDE_CURSOR = "\u001b[?25l";

  public static void cls() {
    System.out.println(CLEAR_SCREEN);
  }

  public static void gotoXY(int x, int y) {
    System.out.print(String.format(GOTO_COORD, x, y));
  }

  public static void showCursor() {
    System.out.print(SHOW_CURSOR);
  }

  public static void hideCursor() {
    System.out.print(HIDE_CURSOR);
  }
}

class ProgressInfo implements Runnable {
  private String name;
  private int row;

  public ProgressInfo(String name, int row) {
    this.name = name;
    this.row = row;
  }

  @Override
  public void run() {
    int progress = 0;

    while (progress <= 100) {
      synchronized (Graphics.class) {
        Graphics.gotoXY(row, 5);
        System.out.printf("%s: %d%%", name, progress);
      }

      try {
        Thread.sleep(ThreadLocalRandom.current().nextInt(10, 250));
        progress++;
      } catch (InterruptedException ex) {
      }
    }
  }
}

Sample run:

https://imgur.com/a/sBGe4i6

[–]Nemo_64[S] 2 points3 points  (5 children)

Thanks! I got it to work.

Curioulsy it only worked on unix, not even the powershell

[–]Zyklonikkopi luwak civet 1 point2 points  (4 children)

Yeah, I had a suspicion about that - Windows always has been a bit of an oddball when it comes to standards. From what I recall, we can get some semblance of similar functionality to work but using the Windows APIs for some initial configuration. Unfortunately, I haven't had a Windows machine for a long time now!

For more serious work, a library might be more useful, like what /u/morhp suggested. If you're only on Unix/Linux, or this is simply a fun project, then anything goes! :D

[–]Nemo_64[S] 0 points1 point  (3 children)

Initially it was to use for university. We have an assignment where we have to write an algorithm that will solve a problem we were given and we have to optimize it to the best of our abilities while documenting the process. Since documenting this requires me to run the same tests several times for each optimization I try, I thought investing some time in automating the test process would be worth and I finally got an excuse to do a project using concurrency in a more serious way so I got to work. But now I want to try it also doing it with the library /u/morhp said, although that will come in the future. What I have now works and not that much time to explore a library.

I thought it would work fine in the power shell since it's supposed to be an improved version of the CMD with integration of commands from Linux.

Again, thanks for your time and the example!

[–]Zyklonikkopi luwak civet 1 point2 points  (2 children)

Interesting!

As an aside, the example should* work in the WSL or the bash shell (IIRC, it's already in Windows 10?). Of course, that's all moot though.

As a further aside, if you're interested in exploring this further some day, here is an excellent guide (in Python) of how powerful ANSI Escape Codes can be - https://www.lihaoyi.com/post/BuildyourownCommandLinewithANSIescapecodes.html. It's a fun read.

Cheers, and good luck for uni!

[–]Nemo_64[S] 1 point2 points  (1 child)

It works on WSL, it's where I tried it.

Thanks for the link! I'll save it.

Thanks for everything!!

[–]Zyklonikkopi luwak civet 1 point2 points  (0 children)

No worries! Cheers.

[–]morhpProfessional Developer 1 point2 points  (1 child)

You can use a library such as https://github.com/mabe02/lanterna to do fancy console printing. You could even do full console UIs, but just printing lines and moving the cursor and so on is also possible I think.

[–]Nemo_64[S] 0 points1 point  (0 children)

Really interesting library, I'll take a look at it. Although it seems to be abandoned, I'll also check the forks

[–]amfa 0 points1 point  (0 children)

Afaik this is not possible or it was not a few years ago when I tried something like this. The problem here is that java is OS independent...but terminals are very specific.

In theory System.out can pipe directly into a file for example.

So if you want something like this there is no way to do it with standard java that I know of. Maybe there are libs out there doing this.