【问题标题】:Java capture process output with colorJava 用颜色捕获进程输出
【发布时间】:2018-01-29 01:39:46
【问题描述】:

有没有办法从带有颜色格式数据的进程中捕获控制台输出?目前我只捕获文本输出:

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 以供用户查看此过程的日志,但它很难阅读,因此我想从控制台复制颜色。

Here is an example 如何在 Go 中完成,但是这可以在 Java 中完成吗?

此应用程序将在 Windows 上运行,但如果它也可以通过从 Shell 或 Bash 读取相同的颜色数据在 Linux 或 MacOS 上运行,那就太好了。

【问题讨论】:

  • 捕获的输出是由批处理文件还是由应用程序完成的?控制台中的文本着色是如何完成的?是使用ANSI escape sequences 还是直接修改控制台的属性来完成。捕获的文本流缓冲区只能是字符,而不是输出字符的图形表示。
  • 我正在运行 msbuild 命令来构建 C# 解决方案:msdn.microsoft.com/en-us/library/0k6kkbsd.aspx
  • 请提供有关控制台中文本“着色”的更多详细信息以及一些指示它是什么颜色的示例输出。
  • @Bohemian 问题不在于如何打印颜色。它是关于如何从 ProcessBuilder 的输出中找到现有的颜色数据。换句话说,我有一个将彩色文本输出到 bash 或 cmd 的现有进程,但我需要我的 Java 应用程序来读取文本内容和 文本颜色。例如here is how it is done in Go。我如何在 Java 中做同样的事情?
  • 如果我需要使用 BufferedReader(如上所示)或 ProcessBuilder 以外的东西来运行我的 cmd/bash 脚本来生成对我来说可以的输出。

标签: java cmd


【解决方案1】:

您面临的问题与 Java 功能并不完全相关。

发生的情况是,许多程序检查标准输入是终端还是管道,并以不同的方式生成输出,例如删除颜色格式。有时解决方法直接存在通过使用特殊选项来强制生成这些颜色格式1

如果这在您使用的二进制文件中不可用,显然唯一的解决方案是编写自己的伪 tty,使目标二进制文件认为它与常规 tty 对话。

您可以尝试使用此处提供的代码2,或者您可以查看JetBrains/pty4j,看看是否可以根据您的需要进行调整。

【讨论】:

  • 谢谢! pty4j 对我来说效果很好,不需要调整。它输出文本前面的颜色代码供我使用。这不是我的问题,所以我不能接受答案,但这里有 200 赏金给你。我也会发布一个更具体的答案。
【解决方案2】:

正如@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

【讨论】:

    猜你喜欢
    • 2017-05-14
    • 1970-01-01
    • 1970-01-01
    • 2016-07-21
    • 2021-10-03
    • 1970-01-01
    • 2011-02-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多