如何在Windows上的Java中使用vt100转义代码

时间:2018-10-11 19:29:36

标签: java windows cmd vt100

vt100转义码是一种强大且流行的方法,用于格式化xterm或konsole等虚拟终端上的输出(颜色,位置,闪烁,下划线等)。参见https://en.wikipedia.org/wiki/ANSI_escape_code

当您在xterm,konsole等中运行Java程序并使用System.out.print这样的代码时-例如

// print "Hello, World!" in red
System.out.print("\u001b[31mHello, World!");

java将它们原封不动地传递给终端,因此这些终端随后将解释代码并按您期望的方式运行。

尽管Java程序应该是独立于平台的,但是当您从Windows命令提示符运行这样的程序时,您将看到打印出的代码,如下所示:

☐[31mHello, World!

在寻找解决此问题的方法之后,我找不到简单的解决方案,甚至找不到关于该主题的讨论。大多数解决方案都依赖于在其他控制台应用程序中运行程序或将基于Java的自定义控制台包含到程序中。

那么-如何在Windows默认命令提示符下轻松使用vt100格式的文本?

1 个答案:

答案 0 :(得分:1)

我不知道这是否适用于旧版Windows(欢迎一些反馈-我已经在Windows 10上对其进行了测试),但是我从https://docs.microsoft.com/en-us/windows/console/console-virtual-terminal-sequences的底部提取了代码并进行了翻译到Java。

这使用了对kernel32.dll的一些调用,因此我不得不合并Java Native Access(JNA)。要运行此程序,您需要从以下位置下载jna-*version*.jarjna-platform-*version*.jar https://github.com/java-native-access/jna#download并将它们包含在您的项目中。

然后,添加以下导入:

import com.sun.jna.*;
import com.sun.jna.platform.win32.WinDef.*;
import com.sun.jna.platform.win32.WinNT.HANDLE;

在程序的开头,您可以通过运行以下代码来启用vt100:

if(System.getProperty("os.name").startsWith("Windows"))
{
    // Set output mode to handle virtual terminal sequences
    Function GetStdHandleFunc = Function.getFunction("kernel32", "GetStdHandle");
    DWORD STD_OUTPUT_HANDLE = new DWORD(-11);
    HANDLE hOut = (HANDLE)GetStdHandleFunc.invoke(HANDLE.class, new Object[]{STD_OUTPUT_HANDLE});

    DWORDByReference p_dwMode = new DWORDByReference(new DWORD(0));
    Function GetConsoleModeFunc = Function.getFunction("kernel32", "GetConsoleMode");
    GetConsoleModeFunc.invoke(BOOL.class, new Object[]{hOut, p_dwMode});

    int ENABLE_VIRTUAL_TERMINAL_PROCESSING = 4;
    DWORD dwMode = p_dwMode.getValue();
    dwMode.setValue(dwMode.intValue() | ENABLE_VIRTUAL_TERMINAL_PROCESSING);
    Function SetConsoleModeFunc = Function.getFunction("kernel32", "SetConsoleMode");
    SetConsoleModeFunc.invoke(BOOL.class, new Object[]{hOut, dwMode});
}

从那时起

System.out.print("\u001b[31mHello, World!");

将打印“你好,世界!”像预期的那样显示为红色。