如何删除已经打印到控制台/终端上的先前字符?

4
有没有一种方法可以动态地更改Java中的输出?例如,在终端窗口中如果我有:
```java System.out.println("Hello"); ```
然后我希望在程序运行时能够更改"Hello"这个输出结果。
System.out.print("H")

然后我有:

System.out.print("I")

输出结果为:
HI

有没有一种方法可以为输出分配一个位置,以便能够动态地替换字符?例如(我知道这不会输出我想要的结果,我只是想说明我的思路):

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

它将首先打印出:

H

然后过一秒钟,用 I 替换 H?

我知道这听起来很蠢,但我对不使用 GUI 动态更改内容很感兴趣。有人可以指导我这种技术吗?非常感谢您的帮助。


1
在控制台中,你不能这样做。你不能省略已经显示的输出,而不重新执行你的代码。 - Rohit Jain
好的,谢谢!那就是我需要知道的全部了! - eatonphil
1
可能是重复问题:https://dev59.com/amsz5IYBdhLWcg3w_NED - dan
4个回答

2

您可能想要看一下

System.out.printf

看这里的例子:http://masterex.github.com/archive/2011/10/23/java-cli-progress-bar.html 编辑: printf 显示格式化字符串,这意味着您可以适应该格式并根据需要进行更改。
例如,您可以像这样做:
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
    }
}

使用这里找到的格式化字符串语法:http://docs.oracle.com/javase/6/docs/api/java/util/Formatter.html#syntax 如注释所述,此解决方案仅限于单行,但根据您的需求,这可能已足够。
如果您需要整个屏幕的解决方案,那么一个可能的解决方案将是(尽管相当肮脏)使用JNA挂钩操作系统并获取控制台窗口的句柄,找到它的高度,然后循环println()以“清除”窗口,然后重新绘制输出。
如果您想阅读更多内容,我可以回答更多问题或者这里有一个链接:https://github.com/twall/jna

该示例的局限性在于它仅展示了如何重绘当前行。 - millimoose
我更新了帖子并添加了更多关于printf和替代解决方案的内容。 - Oliver Atkinson
另一件让我想到的事情是:我相信\r仅仅是将光标移动到行首,意味着它不会删除之前写下的所有内容 - 您只是覆盖了先前的字符。这意味着如果要用较短的行替换一行,则有些棘手,您必须使用空格覆盖其余部分。 - millimoose
我刚刚去验证了上述内容,确实是这样的。 - millimoose
"\r"在编程中代表回车符,意味着光标将返回到行的开头。如果您想要清除一行以缩短其长度,可以使用填充方式。使用以下代码:System.out.println(String.format("[%-20s]", "地球"));可以得到输出结果:[地球 ] (在“地球”后面有15个空格) - Oliver Atkinson
哦,我不是说你的回答有问题,只是这是一个非显而易见的警告,既不会出现在进度条示例中,也不会出现在你的示例代码中。(两个示例都逐渐变长。) - millimoose

2
您可以使用\b来退格和删除前一个字符。
$ 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

这段代码会输出 H,然后在一秒后用 I 替换它。

不幸的是,在Eclipse控制台中无法工作,但在普通控制台中可以。


2
这是你需要的内容(使用回车符'\r'来覆盖之前的输出):
  System.out.print("H");
  Thread.sleep(1000);
  System.out.print("\rI");

1
通常用于此类操作的C库称为curses。(也可从依赖于C库绑定的脚本语言(如Python)中使用。)您可以使用Java绑定,例如JCurses。Google还告诉我,有一个纯Java等效库可用,称为lanterna

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接