4

Is there a way to dynamically change output in Java? For instance, in a terminal window if I have:

System.out.print("H")

and then I have:

System.out.print("I")

The output will be:

HI

Is there a way to assign a position to outputs that allows you to replace characters dynamically? For instance (and I know this would not output what I want, I merely want to demonstrate my thinking) this:

 System.out.print("H")
 Thread.sleep("1")
 System.out.print("I")

And it would first print out

H

and then after a second, replace the H with an I?

I'm sure this sounds stupid, I am just interested in dynamically changing content without GUIs. Can someone point me in the direction for this technique? Thank you very much in advance.

try-catch-finally
  • 7,436
  • 6
  • 46
  • 67
eatonphil
  • 13,115
  • 27
  • 76
  • 133
  • 1
    Well, in console you can't do that. You cannot omit the output that already has been displayed, without re-executing your code. – Rohit Jain Oct 30 '12 at 19:55
  • Ok thanks! That's all I needed to know then! – eatonphil Oct 30 '12 at 19:56
  • 1
    Possible duplicate: http://stackoverflow.com/questions/7522022/how-to-delete-stuff-printed-to-console-by-system-out-println – dan Oct 30 '12 at 20:13

4 Answers4

2

You might want to take a look at

System.out.printf

Look at the example shown here: http://masterex.github.com/archive/2011/10/23/java-cli-progress-bar.html

edit:

printf displays formatted strings, which means you can adapt that format and change it for your needs.

for example you could do something like:

String[] planets = {"Mars", "Earth", "Jupiter"};        
String format = "\r%s says Hello";

for(String planet : planets) {
    System.out.printf(format, planet);
try { 
        Thread.sleep(1000); 
    }catch(Exception e) { 
        //... oh dear
    }
}

Using the formatted string syntax found here: http://docs.oracle.com/javase/6/docs/api/java/util/Formatter.html#syntax

As the comment says this solution is only limited to a singular line however dependent on your needs this might be enough.

If you require a solution for the whole screen then a possible solution would be (although quite dirty) would be to hook the operating system using JNA and get a handle on the console window, find its height and then loop println() to "clear" the window then redraw your output.

If you would like to read more then I can answer more questions or here is a link: https://github.com/twall/jna

Oliver Atkinson
  • 7,970
  • 32
  • 43
  • A limitation of that example is that it only show how to redraw the current line. – millimoose Oct 30 '12 at 20:06
  • I updated the post with some more content regarding printf and an alternate solution – Oliver Atkinson Oct 30 '12 at 20:22
  • Another thing that comes to mind: I believe `\r` merely moves the cursor to the start of the line. Meaning that it wouldn't delete everything you've written before – you're overwriting the previous characters instead. This means it's somewhat tricky to replace a line with a shorter line, you have to overwrite the rest with spaces. – millimoose Oct 30 '12 at 20:53
  • (I just went and verified the above, that's indeed what happens.) – millimoose Oct 30 '12 at 21:00
  • well \r stands for "The carriage-return character" and means it will return to the beginning of the line, if you wanted to clear the line for a shorter line you could use padding System.out.println(String.format("[%-20s]", "Earth")); will give you: [Earth ] (15 spaces after earth) – Oliver Atkinson Oct 30 '12 at 21:12
  • Oh, I'm not saying it's a problem with your answer, just that it's a nonobvious caveat that wouldn't show up with either the progressbar example or your sample code. (The text written gets progressively longer in both.) – millimoose Oct 30 '12 at 21:16
2

You can use \b to backspace and erase the previous character.

$ cat T.java
import java.lang.Thread;

public class T {
    public static void main(String... args) throws Exception {
        System.out.print("H");
        System.out.flush();
        Thread.sleep(1000);
        System.out.print("\bI\n");
        System.out.flush();
    }
}
$ javac T.java && java T
I

It will output H, then replace it with I after one second.

Sadly, it doesn't work in Eclipse console, but in normal console it does.

Alex
  • 25,147
  • 6
  • 59
  • 55
2

This is what you need (uses carriage return '\r' to overwrite the previous output):

  System.out.print("H");
  Thread.sleep(1000);
  System.out.print("\rI");
Andrey Mormysh
  • 809
  • 5
  • 12
1

The C library that is usually used to do this sort of thing is called curses. (Also used from scripting languages that rely on bindings to C libraries, like Python.) You can use a Java binding to it, like JCurses. Google also tells me a pure-Java equivalent is available, called lanterna.

try-catch-finally
  • 7,436
  • 6
  • 46
  • 67
millimoose
  • 39,073
  • 9
  • 82
  • 134