Java如何捕获带有颜色的进程输出

7

有没有一种方法可以捕获带有颜色格式数据的进程控制台输出?目前我只能捕获文本输出:

ProcessBuilder pb = new ProcessBuilder("cmd.exe", "/C", "mvn dependency:resolve");
// mvn dependency:resolve is an example of a process that outputs color
Process p = builder.start();
BufferedReader br = new BufferedReader(new InputStreamReader(p.getInputStream()));
String line = null;
while ((line = reader.readLine()) != null) 
{
   System.out.println(line);
}

但是我无法找到一种捕获此文本颜色数据的方法。彩色文本似乎不以任何特殊字符或其他方式开头。
我将打印此捕获的文本到UI,以便用户看到此过程的日志,但很难阅读,因此我想从控制台复制颜色。
这里有一个Go语言的示例,但是Java能做到吗?
此应用程序将在Windows上运行,但如果可以通过从Shell或Bash读取相同的颜色数据来在Linux或MacOS上工作,那就太好了。

1
输出是由批处理文件还是应用程序捕获的?控制台中的文本着色是如何实现的?是通过ANSI转义序列还是直接修改控制台属性来完成的?捕获只能使用文本流缓冲区,仅包含字符而不是输出字符的图形表示。 - Mofi
我正在运行msbuild命令来构建C#解决方案: https://msdn.microsoft.com/zh-cn/library/0k6kkbsd.aspx - František Jeřábek
请提供有关控制台中文本“着色”的更多细节,并提供一些示例输出以指示其颜色。 - Bohemian
@Bohemian 这个问题不是关于如何打印颜色,而是如何从ProcessBuilder的输出中找到现有的颜色数据。换句话说,我有一个现有的进程将彩色文本输出到bash或cmd,但我需要我的Java应用程序读取文本内容和文本颜色。例如这里是Go中的实现方式。我该如何在Java中实现相同的功能? - egerardus
如果我需要使用除了上面显示的BufferedReader以外的其他东西,或者使用除ProcessBuilder之外的其他东西来运行我的cmd/bash脚本以生成输出,那对我来说也没问题。 - egerardus
2个回答

7
你面临的问题并不完全与Java能力有关。许多程序会检查stdin是终端还是管道,并以不同方式生成输出,例如放弃颜色格式。有时,通过使用特殊选项直接强制生成这些颜色格式的解决方法是存在的1
如果您正在使用的二进制文件中没有此选项,则显然唯一的解决方案是编写自己的伪tty,使目标二进制文件认为它正在与常规tty通信。
您可以尝试使用此处提供的代码2,或者查看JetBrains/pty4j,看看是否可以根据您的需求进行调整。


谢谢!pty4j 对我来说非常好用,无需调整。它可以在文本前输出颜色代码供我使用。虽然这不是我的问题,所以我不能接受答案,但我会给你200赏金。我也会发布一个带更多细节的答案。 - egerardus

1

正如 @nvidot 所提到的那样,pty4j 是一个不错的选择:

public static void main(String[] args) throws IOException, InterruptedException
{
    try
    {

        String[] cmd = { "cmd", "/C", "mvn clean" };
        String workingDir = "d:\\test";
        PtyProcess pty = PtyProcess.exec(cmd, null, workingDir);
        InputStream is = pty.getInputStream();
        BufferedReader reader = new BufferedReader(new InputStreamReader(is));
        String line = null;
        while ((line = reader.readLine()) != null) 
        {
            System.out.println(line);
        }
        int result = pty.waitFor();
    }
    catch (Exception e)
    {
        e.printStackTrace();
        e.getCause().printStackTrace();
    }
    
}

这给了我以下输出结果: (显然需要进行一些清理,但颜色代码在其中清晰可见且准备好解析,例如:“94m”,“92m”,“36m”等)
[0m[0K[[0;34;94mINFO[0m] Scanning for projects...[0K[?25l
[0K[?25h[[0;34;94mINFO[0m][0K[?25l
[[0;34;94mINFO[0m] [0;1m-----------------------------< [0;36mtest:test[0;1m >------------------------------[0m[0K
[[0;34;94mINFO[0m] [0;1mBuilding test 1.0-SNAPSHOT[0m[0K
[[0;34;94mINFO[0m] [0;1m----------[0m[0K[15G[?25h[?25l
[[0;34;94mINFO[0m] [0;1m--------------------------------[ jar ]---------------------------------[0m[0K
[0K[?25h[[0;34;94mINFO[0m][0K[?25l
[[0;34;94mINFO[0m] [0;1m--- [0;32mmaven-clean-plugin:3.1.0:clean[0m [0;1m(default-clean)[0m @ [0;36mtest[0;1m ---[0m[0K
[0K[?25h[[0;34;94mINFO[0m] [0;1m------------------------------------------------------------------------[0m[0K[?25l
[[0;34;94mINFO[0m] [0;32;92mBUILD SUCCESS[0m[0K
[[0;34;94mINFO[0m] [0;1m--------------[0m[0K[16G[?25h[?25l
[[0;34;94mINFO[0m] [0;1m------------------------------------------------------------------------[0m[0K
[[0;34;94mINFO[0m] Total time:  1.924 s[0K
[[0;34;94mINFO[0m] Finished at: 2020-10-19T12:36:46-07:00[0K
[[0;34;94mINFO[0m] [0;1m------------------------------[0m[0K[32G[?25h[?25l
[[0;34;94mINFO[0m] [0;1m------------------------------------------------------------------------[0m[0K
[0K[?25h

是否存在一个现有的TextPane或TextArea可以解释这些代码并正确显示它们? - chrish

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