HOWTO · Java

如何在 Java 中清除控制台

它展示了在 Java 中清理控制台屏幕的两种方法。

本页内容

Java 没有内置的控制台清除方法。程序运行期间,你可以输出 ANSI 转义序列,或启动操作系统提供的命令。哪种方法有效,取决于显示程序的终端或 IDE。两种方法都是要求显示设备清除可见区域;它们都无法保证删除滚动缓冲区中的旧输出或 IDE 保存的运行历史。
控制台处理是 Java 教程 收集的日常实用工具之一。

使用 ANSI 转义序列清除控制台

ANSI 序列是由终端解释的控制字符。序列 \033[H 会将光标移至起始位置,\033[2J 会擦除可见屏幕。在显示下一条提示或状态消息之前输出这两个序列。\033[2J 会擦除整个显示区域;从光标位置开始擦除的行为由其他擦除显示参数实现,例如 \033[0J 会擦除从光标到显示区域末尾的内容。

运行以下示例:

本节中的代码以及显示的标签或输出仍为英文。

public class ClearConsole {
    public static void main(String[] args) {
        System.out.print("\033[H\033[2J");
        System.out.flush();
        System.out.println("Console cleared!");
    }
}
Console cleared!

Java 字符串转义 \033 会插入 ESC 字符。System.out.flush() 会及时发送这些序列;如果不调用它,缓冲的输出可能不会在后续输出之前到达终端。此代码会发出清除请求,但无法让不支持该序列的终端解释它。终端模拟器通常支持 ANSI,但实际效果可能取决于终端设置、IDE 配置以及程序的启动方式。清除可见屏幕后,终端的滚动缓冲区中也可能仍保留历史内容。如果转义字符原样显示,或屏幕没有变化,请使用 IDE 的清除控制台命令,或检查其 ANSI 支持设置。示例中的代码和输出块保持原样,其中显示的文字仍为英文。

使用 ProcessBuilder 运行操作系统命令

如果终端提供清屏命令,Java 可以通过 ProcessBuilder 启动该命令。Windows 命令提示符通过 cmd /c 使用 cls;macOS 和其他类 Unix 系统通常提供 clear。示例使用 Locale.ROOT 将操作系统名称转为小写,并检查名称是否以 windows 开头,因此 macOS(Darwin)会进入类 Unix 系统分支。应根据实际操作系统选择命令,不要假设所有非 Windows 系统都使用同一个命令。此示例会先检查是否存在交互式控制台,因为清除终端的命令无法清除文件,也无法清除未连接到终端的 IDE 面板:

本节中的代码以及显示的标签或输出仍为英文。

import java.io.IOException;
import java.util.Locale;

public class ClearConsoleWithCommand {
    public static void main(String[] args) {
        if (System.console() == null) {
            System.out.println("No interactive console is attached.");
            return;
        }
        try {
            String os = System.getProperty("os.name").toLowerCase(Locale.ROOT);
            ProcessBuilder builder = os.startsWith("windows")
                    ? new ProcessBuilder("cmd", "/c", "cls")
                    : new ProcessBuilder("clear");
            builder.inheritIO();
            Process process = builder.start();
            int exitCode = process.waitFor();
            if (exitCode != 0) {
                System.out.println("The clear command returned " + exitCode + ".");
            }
        } catch (IOException e) {
            System.out.println("The clear command could not be started.");
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            System.out.println("Waiting for the clear command was interrupted.");
        }
    }
}

ProcessBuilder 会启动一个独立进程;如果命令不存在或不在进程的搜索路径中,它不会让该命令变得可用。inheritIO() 会将子进程连接到与 Java 进程相同的标准输入、输出和错误流,使终端命令能够影响已连接的显示设备。示例会等待命令完成,并报告非零退出码。如果等待期间发生中断,示例也会恢复线程的中断状态。命令仍可能因为不存在、环境缺少终端信息,或进程没有在可用的交互式终端中启动而失败。操作系统检查只能选择一个可能适用的命令,不能证明该命令确实存在,也不能保证终端会执行清屏操作。示例中的代码和输出块保持原样,其中显示的文字仍为英文。

检查终端和操作系统支持情况

当你确定终端会解释 ANSI 控制序列时,可以使用 ANSI 方法。它不依赖外部命令;如果应用环境能够控制终端行为,这种方法就很适用。只有在所选命令确实存在且能够访问同一个交互式终端时,才使用进程方法;IDE 运行面板、重定向的输出和后台任务可能与终端的行为不同。即使 IDE 显示了类似控制台的面板,在 IDE 中运行程序或重定向输入、输出时,System.console() 也可能为 null。这两种方法都无法可靠地清除滚动缓冲区或所有 IDE 的控制台视图。如果显示内容没有变化,请检查终端的 ANSI 设置以及程序是否连接到交互式终端;需要清除 IDE 视图时,优先使用 IDE 自带的清除控制台控件。