如何给System.out.println输出添加颜色?

132

我该如何在Java中着色输出?

比如说,在C和其他编程语言中,我可以使用类似于ANSI转义序列的\033[0m来实现这一点。但是在Java中却不行。

public static void main(String[] x) {
    System.out.println("\033[0m BLABLA \033[0m\n");
}
13个回答

130

注意

你可能无法为Windows的cmd提示符设置颜色,但它应该适用于许多Unix(或类Unix)终端。

另外,请注意,一些终端可能根本不支持一些(如果有的话)ANSI转义序列,特别是24位颜色。

用法

请参考底部的Curses部分以获取最佳解决方案。对于个人或简单的解决方案(虽然不是跨平台解决方案),请参考ANSI转义序列部分。


简而言之

  • java: System.out.println((char)27 + "[31m" + "ERROR MESSAGE IN RED");

  • python: print(chr(27) + "[31m" + "ERROR MESSAGE IN RED")

  • bashzshprintf '\x1b[31mERROR MESSAGE IN RED'
    • 这也可能适用于Os X:printf '\e[31mERROR MESSAGE IN RED'
  • shprintf 'CTRL+V,CTRL+[[31mERROR MESSAGE IN RED'
    • 例如,按顺序按下CTRL+VCTRL+[以在不可用转义时获得“原始”ESC字符
    • 如果操作正确,则应看到一个^[。虽然它看起来像两个字符,但实际上只是一个ESC字符。
    • 您也可以在任何编程或脚本语言中使用vimCTRL+VCTRL+[,因为它使用文字ESC字符
    • 另外,您可以用ESC替换Ctrl+[ … 例如,您可以使用CTRL+VESC,但我发现前者更容易,因为我已经按下了CTRL,并且因为[不那么麻烦。

ANSI转义序列

转义序列简介

虽然这不是最好的做法,但在编程或脚本语言中最简单的方法是使用转义序列。来自该链接的内容如下:

转义序列是一系列用于改变计算机及其附加外围设备状态的字符。它们也被称为控制序列,反映了它们在设备控制方面的用途。

ANSI转义序列简介

然而,在视频文本终端中,使用ANSI转义序列会更容易。来自该链接的内容如下:

ANSI转义序列是一种标准的信令方式,用于控制视频文本终端上的光标位置、颜色和其他选项。某些字节序列,大多以“Esc”和“[''开始,嵌入到文本中,终端会将其解析为命令,而不是字符代码。

如何使用ANSI转义序列

通常情况下

  • 转义序列以转义字符开头;对于ANSI转义序列来说,序列始终以ESC(ASCII:27 / 十六进制:0x1B)开始。
  • 要了解可以使用的内容列表,请参阅维基百科上的ANSI转义序列列表

在编程语言中

一些编程语言(如Java)不会将\e\x1b解释为ESC字符。但是,我们知道ASCII字符27ESC 字符,因此我们可以将27强制转换为char并使用它来开始转义序列。

以下是在常见编程语言中执行此操作的一些方法:

  • Java

    • System.out.println((char)27 + "[33m黄色");
  • Python 3

    • print(chr(27) + "[34m蓝色");
    • print("\x1b[35m洋红色");
      • 请注意,\x1b 在Python中也可以正确解释
  • Node JS

    • 以下内容不会在Web控制台中以JavaScript形式显示颜色
    • console.log(String.fromCharCode(27) + "[36m青色");
    • console.log("\x1b[30;47m黑色背景白色字体");
      • 请注意,\x1b 在node中也可以使用

在Shell提示符或脚本中

如果你正在使用bashzsh,那么在大多数终端中着色输出是非常容易的。在Linux、Os X和一些Windows终端中,你可以通过以下两种方式检查终端是否支持颜色:
  • printf '\e[31mRED'
  • printf '\x1b[31mRED'

如果两者都有颜色,那就太好了!如果只有一个有颜色,则使用该序列。如果两者都没有颜色,请仔细检查你输入的内容是否正确,并确保你正在使用bash或zsh;如果你仍然看不到任何颜色,则你的终端可能不支持ANSI转义序列。

如果我没记错的话,Linux 终端通常支持 \e\x1b 转义序列,而 OS X 终端通常只支持 \e,但我可能错了。不过,如果你看到类似下面的图片,那么你就准备好了!(请注意,我正在使用 shell zsh,它正在着色我的提示字符串;另外,我在 Linux 中使用 urxvt 作为终端。)

ANSI Escape Sequences Coloring Text Red

你可能会问:"这是如何工作的?"。基本上,printf 解释了接下来的字符序列(即 单引号内的所有内容)。当 printf 遇到 \e\x1b 时,它将把这些字符转换为 ESC 字符(ASCII:27)。这正是我们想要的。现在,printf 发送了 ESC31m,由于有一个 ESC 后跟一个有效的 ANSI 转义序列,因此我们应该得到彩色输出(只要终端支持)。
你也可以使用 echo -e '\e[32mGREEN'(例如)来着色输出。请注意,echo-e 标志 "启用反斜杠转义的解释",如果您希望 echo 正确解释转义序列,则必须使用该标志。

更多有关 ANSI 转义序列的信息

ANSI 转义序列不仅可以用于输出颜色,但我们先从这个开始,详细了解颜色是如何工作的。然后,我们将看到如何操纵光标。最后,我们将介绍如何使用 8 位颜色和 24 位颜色(虽然它只有薄弱的支持)。

Wikipedia 上,他们将 ESC[ 称为 CSI,所以我也将这样做。

颜色

使用 ANSI 转义序列实现彩色输出,请使用以下代码:

  • CSI n m
    • CSI: 转义字符—^[[ESC[
    • n: 一个数字,下列之一:
      • 30-37, 39: 前景色
      • 40-47, 49: 背景色
    • m: 一个字面上的 ASCII m—终止转义序列

我将使用 bash 或 zsh 来演示所有可能的颜色组合。将以下内容放入 bash 或 zsh 中以查看结果 (您可能需要将 \e 替换为 \x1b):

  • for fg in {30..37} 39; do for bg in {40..47} 49; do printf "\e[${fg};${bg}m~TEST~"; done; printf "\n"; done;

结果:

various foreground/background colors using ANSI escapes

快速参考(颜色)

+~~~~~~+~~~~~~+~~~~~~~~~~~+
|  fg  |  bg  |  color    |
+~~~~~~+~~~~~~+~~~~~~~~~~~+
|  30  |  40  |  black    |
|  31  |  41  |  red      |
|  32  |  42  |  green    |
|  33  |  43  |  yellow   |
|  34  |  44  |  blue     |
|  35  |  45  |  magenta  |
|  36  |  46  |  cyan     |
|  37  |  47  |  white    |
|  39  |  49  |  default  |
+~~~~~~+~~~~~~+~~~~~~~~~~~+

选择图形渲染(SGR)

SGR只允许您更改文本。其中许多在某些终端中不起作用,因此在生产级项目中要谨慎使用。但是,它们可以有助于使程序输出更易读或帮助您区分不同类型的输出。

颜色实际上属于SGR,因此语法相同:

  • CSI n m
    • CSI: 转义字符—^[[ESC[
    • n: 一个数字,可以是以下数字之一:
      • 0: 重置
      • 1-9: 打开各种文本效果
      • 21-29: 关闭各种文字效果(比 1-9 更少支持)
      • 30-37, 39: 前景色
      • 40-47, 49: 背景色
      • 38: 8位或24位前景色(参见下面的8/24位颜色
      • 48: 8位或24位背景色(参见下面的8/24位颜色
    • m: 一个字面上的 ASCII m—终止转义序列
尽管对于模糊(2)、斜体(3)、下划线(4)、闪烁(5,6)、反向视频(7)、隐藏(8)和删除线(9)的支持不牢固,但在Linux和OS X终端上有些(但很少全部)会起作用。值得注意的是,您可以使用分号将上述任何属性分开。例如,printf '\e[34;47;1;3mCRAZY TEXT\n' 将显示 CRAZY TEXT,具有 蓝色前景白色背景,并且它将是 粗体斜体 的。例如:

string attributes together example screenshot

将以下内容放入您的bash或zsh shell中,以查看您可以执行的所有文本效果。(您可能需要将\e替换为\x1b。)

  • for i in {1..9}; do printf "\e[${i}m~TEST~\e[0m "; done

结果:

SGR state 1 SGR state 2

你可以看到,我的终端支持除了暗淡(2)、隐藏(8)和删除线(9)之外的所有文本效果。

快速参考(SGR属性0-9)

+~~~~~+~~~~~~~~~~~~~~~~~~+
|  n  |  effect          |
+~~~~~+~~~~~~~~~~~~~~~~~~+
|  0  |  reset           |
|  1  |  bold            |
|  2  |  faint*          |
|  3  |  italic**        |
|  4  |  underline       |
|  5  |  slow blink      |
|  6  |  rapid blink*    |
|  7  |  inverse         |
|  8  |  conceal*        |
|  9  |  strikethrough*  |
+~~~~~+~~~~~~~~~~~~~~~~~~+

* not widely supported
** not widely supported and sometimes treated as inverse

8位色彩

虽然大多数终端都支持此功能,但它比0-79颜色的支持要少。

语法:

  • CSI 38;5; n m
    • CSI:转义字符—^[[ESC[
    • 38;5;:表示使用8位色彩的文字字符串,用于前景色
    • n:数字之一,如下所示:
      • 0-255

如果您想以一种漂亮的方式预览终端中的所有颜色,我在gist.github.com上有一个不错的脚本

它看起来像这样:

8-bit color example screenshot

如果您想使用8位颜色更改背景,只需将38替换为48
  • CSI 48;5; n m
    • CSI:转义字符—^[[ESC[
    • 48;5;:表示使用8位颜色作为背景的文字字符串
    • n:数字之一:
      • 0-255

24位彩色

也称为真彩色,24位彩色提供了一些非常酷的功能。支持此功能的终端正在不断增加(据我所知,在除了我的终端urxvt之外的大多数现代终端中都可以使用)。

24位色实际上在vim中得到支持(请参见vim wiki以了解如何启用24位色)。这很棒,因为它从gvim定义的配色方案中提取;例如,它使用highlight guibg=#______ guifg=#______中的fg/bg来生成24位颜色!很不错,对吧?
下面是24位色的工作原理:
- CSI 38;2; r ; g ; b m - CSI:转义字符——^[[ESC[ - 38;2;:表示前景色使用24位颜色的文字字符串 - rgb:数字——每个数字应该是0-255之间的数

为了测试你可以使用的多种颜色(我想是(2^8)^3 或者 2^24 或者 16777216 种可能性),你可以在 bash 或 zsh 中使用以下命令:

  • for r in 0 127 255; do for g in 0 127 255; do for b in 0 127 255; do printf "\e[38;2;${r};${g};${b}m($r,$g,$b)\e[0m "; done; printf "\n"; done; done;

结果(这是在 gnome-terminal 中,因为urxvt 不支持 24 位色彩……请好好工作,urxvt 维护人员……):

24-bit color example screenshot

如果您想要24位颜色作为背景...您猜对了! 您只需将38替换为48:
  • CSI 48;2; r ; g ; b m
    • CSI: 转义字符—^[[ESC[
    • 48;2;: 字面字符串,表示使用24位颜色作为背景
    • r,g,b: 数字—每个数字应该是0-255

插入原始转义序列

有时候\e\x1b无法工作。例如,在sh shell中,有时候两者都不起作用(尽管它在我的系统上现在可以,我认为以前不行)。

为了避免这种情况,您可以使用 CTRL+VCTRL+[CTRLVESC
这将插入一个“原始”的 ESC 字符(ASCII:27)。它看起来像这样^[,但不要担心;它只是一个字符,而不是两个。
例如:

sh raw escape char example screenshot


诅咒

请参考Curses (Programming Library) page,以获取有关curses的完整参考信息。需要注意的是,curses仅适用于类unix操作系统。

使用Curses开始运行

我不会详细介绍,因为搜索引擎可以显示链接到可以比我更好地解释这一点的网站,但我将在此简要讨论并给出一个示例。

为什么要使用Curses而不是ANSI转义?

如果您阅读上面的文本,您可能会记得\e\x1b有时会与printf一起使用。嗯,有时\e\x1b根本不起作用(这不是标准,我从未使用过这样的终端,但这是可能的)。更重要的是,更复杂的转义序列(想象一下Home和其他多字符键)很难支持每个终端(除非您愿意花费大量时间和精力解析terminfo和termcap并找出如何处理每个终端)。

Curses可以解决这个问题。基本上,它能够理解终端的功能,使用这些方法(如上面链接的维基百科文章所述):
大多数curses实现使用一个数据库来描述成千上万种不同终端的功能。有一些实现,比如PDCurses,使用专用设备驱动程序而不是终端数据库。大多数实现使用terminfo;一些使用termcap。Curses具有向字符单元格终端的后向兼容性和简单性的优点。对于不需要位图图形或多种字体的应用程序,使用curses的接口实现通常比使用X工具包的接口实现要简单得多且更快。
大多数情况下,curses将轮询terminfo,然后能够理解如何操作光标和文本属性。然后,您作为程序员,使用curses提供的API来操作光标或更改文本颜色或其他属性,如果您想要的功能是需要的话。
使用Python的示例:
我发现Python非常易于使用,但如果您想在其他编程语言中使用curses,则只需在duckduckgo或任何其他搜索引擎上搜索即可。 :) 这里是Python 3的一个快速示例:
import curses

def main(stdscr):
    # allow curses to use default foreground/background (39/49)
    curses.use_default_colors()

    # Clear screen
    stdscr.clear()

    curses.init_pair(1, curses.COLOR_RED, -1)
    curses.init_pair(2, curses.COLOR_GREEN, -1)
    stdscr.addstr("ERROR: I like tacos, but I don't have any.\n", curses.color_pair(1))
    stdscr.addstr("SUCCESS: I found some tacos.\n", curses.color_pair(2))

    stdscr.refresh() # make sure screen is refreshed
    stdscr.getkey()  # wait for user to press key

if __name__ == '__main__':
    curses.wrapper(main)

结果:

enter image description here

你可能会认为这是一种更加迂回的做法,但实际上它更加跨平台(在Unix和类Unix平台世界中真正跨终端)。对于颜色而言,这并不是非常重要,但是当涉及到支持其他多序列转义序列(例如HomeEndPage UpPage Down等)时,curses变得更加重要。

tput示例

  • tput是一个用于操作光标和文本的命令行实用程序
  • tput随同curses软件包一起提供。如果您希望在终端中使用跨终端(ish)应用程序,则应使用tput,因为它解析terminfo或其他所需内容,并使用一组标准化命令(如curses),然后返回正确的转义序列。
  • 例如:
echo "$(tput setaf 1)$(tput bold)ERROR:$(tput sgr0)$(tput setaf 1) My tacos have gone missing"
echo "$(tput setaf 2)$(tput bold)SUCCESS:$(tput sgr0)$(tput setaf 2) Oh good\! I found my tacos\!"

结果:

example with tput

Tput的更多信息


(char) 27也可以用字符(char)表示(它也可以表示为字符串,因为字符串是一系列字符和转义符“\”及其后面的内容直到“m”被视为单个字符)\u001b或(正如我在ubuntuforums.org上注意到的那样)字符"\003" - dylnmc
1
它在Win7上在Idea14中工作。 - nahab

32

这对我很有效:

System.out.println((char)27 + "[31mThis text would show up red" + (char)27 + "[0m");
您需要使用结尾标记"[37m]"才能将颜色恢复为白色(或其他颜色)。如果您不这样做,可能会使接下来的所有内容都变成“红色”。

酷!你怎么用这种方式换另一种颜色? - Z2VvZ3Vp
2
请参考此问题以获取其他 ANSI 代码:https://dev59.com/hW025IYBdhLWcg3w25uy - Rohit
4
不适用于我... 我尝试使用eclipse内部和从命令提示符调用jar文件。 - Lele

28

4
这篇帖子有一个很好的答案:https://dev59.com/hW025IYBdhLWcg3w25uy#5762502 - codecraig
2
链接现在已经失效。 - YektaDev

13

是的,这完全有可能。

设置类路径=%classpath%; d:\ jansi-1.4.jar;

尝试以下代码:

import org.fusesource.jansi.AnsiConsole;
import static org.fusesource.jansi.Ansi.*;
import static org.fusesource.jansi.Ansi.Color.*;

public class Sample

{

  public static void main(String[] args)
  {
    AnsiConsole.systemInstall();

    System.out.println(ansi().fg(RED).a("Hello World").reset());
    System.out.println("My Name is Raman");

    AnsiConsole.systemUninstall();
  }
}

1
太棒了 - 这是最简单、最直接和视觉上最易理解的通用解决方案! - qraqatit

12
您可以使用 JANSI 库在 Windows 中呈现 ANSI 转义序列。

6

以下是Win32控制台的解决方案。

1)在这里获取JavaNativeAccess库:https://github.com/twall/jna/

2)这两个Java类可以解决问题。

祝使用愉快。

package com.stackoverflow.util;

import com.sun.jna.Library;
import com.sun.jna.Native;
import com.sun.jna.Platform;
import com.sun.jna.Structure;

public class Win32 {
    public static final int STD_INPUT_HANDLE = -10;
    public static final int STD_OUTPUT_HANDLE = -11;
    public static final int STD_ERROR_HANDLE = -12;

    public static final short CONSOLE_FOREGROUND_COLOR_BLACK        = 0x00;
    public static final short CONSOLE_FOREGROUND_COLOR_BLUE         = 0x01;
    public static final short CONSOLE_FOREGROUND_COLOR_GREEN        = 0x02;
    public static final short CONSOLE_FOREGROUND_COLOR_AQUA         = 0x03;
    public static final short CONSOLE_FOREGROUND_COLOR_RED          = 0x04;
    public static final short CONSOLE_FOREGROUND_COLOR_PURPLE       = 0x05;
    public static final short CONSOLE_FOREGROUND_COLOR_YELLOW       = 0x06;
    public static final short CONSOLE_FOREGROUND_COLOR_WHITE        = 0x07;
    public static final short CONSOLE_FOREGROUND_COLOR_GRAY         = 0x08;
    public static final short CONSOLE_FOREGROUND_COLOR_LIGHT_BLUE   = 0x09;
    public static final short CONSOLE_FOREGROUND_COLOR_LIGHT_GREEN  = 0x0A;
    public static final short CONSOLE_FOREGROUND_COLOR_LIGHT_AQUA   = 0x0B;
    public static final short CONSOLE_FOREGROUND_COLOR_LIGHT_RED    = 0x0C;
    public static final short CONSOLE_FOREGROUND_COLOR_LIGHT_PURPLE = 0x0D;
    public static final short CONSOLE_FOREGROUND_COLOR_LIGHT_YELLOW = 0x0E;
    public static final short CONSOLE_FOREGROUND_COLOR_BRIGHT_WHITE = 0x0F;

    public static final short CONSOLE_BACKGROUND_COLOR_BLACK        = 0x00;
    public static final short CONSOLE_BACKGROUND_COLOR_BLUE         = 0x10;
    public static final short CONSOLE_BACKGROUND_COLOR_GREEN        = 0x20;
    public static final short CONSOLE_BACKGROUND_COLOR_AQUA         = 0x30;
    public static final short CONSOLE_BACKGROUND_COLOR_RED          = 0x40;
    public static final short CONSOLE_BACKGROUND_COLOR_PURPLE       = 0x50;
    public static final short CONSOLE_BACKGROUND_COLOR_YELLOW       = 0x60;
    public static final short CONSOLE_BACKGROUND_COLOR_WHITE        = 0x70;
    public static final short CONSOLE_BACKGROUND_COLOR_GRAY         = 0x80;
    public static final short CONSOLE_BACKGROUND_COLOR_LIGHT_BLUE   = 0x90;
    public static final short CONSOLE_BACKGROUND_COLOR_LIGHT_GREEN  = 0xA0;
    public static final short CONSOLE_BACKGROUND_COLOR_LIGHT_AQUA   = 0xB0;
    public static final short CONSOLE_BACKGROUND_COLOR_LIGHT_RED    = 0xC0;
    public static final short CONSOLE_BACKGROUND_COLOR_LIGHT_PURPLE = 0xD0;
    public static final short CONSOLE_BACKGROUND_COLOR_LIGHT_YELLOW = 0xE0;
    public static final short CONSOLE_BACKGROUND_COLOR_BRIGHT_WHITE = 0xF0;

    // typedef struct _COORD {
    //    SHORT X;
    //    SHORT Y;
    //  } COORD, *PCOORD;
    public static class COORD extends Structure {
        public short X;
        public short Y;
    }

    // typedef struct _SMALL_RECT {
    //    SHORT Left;
    //    SHORT Top;
    //    SHORT Right;
    //    SHORT Bottom;
    //  } SMALL_RECT;
    public static class SMALL_RECT extends Structure {
        public short Left;
        public short Top;
        public short Right;
        public short Bottom;
    }

    // typedef struct _CONSOLE_SCREEN_BUFFER_INFO {
    //    COORD      dwSize;
    //    COORD      dwCursorPosition;
    //    WORD       wAttributes;
    //    SMALL_RECT srWindow;
    //    COORD      dwMaximumWindowSize;
    //  } CONSOLE_SCREEN_BUFFER_INFO;
    public static class CONSOLE_SCREEN_BUFFER_INFO extends Structure {
        public COORD dwSize;
        public COORD dwCursorPosition;
        public short wAttributes;
        public SMALL_RECT srWindow;
        public COORD dwMaximumWindowSize;
    }

    // Source: https://github.com/twall/jna/nonav/javadoc/index.html
    public interface Kernel32 extends Library {
        Kernel32 DLL = (Kernel32) Native.loadLibrary("kernel32", Kernel32.class);

        // HANDLE WINAPI GetStdHandle(
        //        __in  DWORD nStdHandle
        //      );
        public int GetStdHandle(
                int nStdHandle);

        // BOOL WINAPI SetConsoleTextAttribute(
        //        __in  HANDLE hConsoleOutput,
        //        __in  WORD wAttributes
        //      );
        public boolean SetConsoleTextAttribute(
                int in_hConsoleOutput, 
                short in_wAttributes);

        // BOOL WINAPI GetConsoleScreenBufferInfo(
        //        __in   HANDLE hConsoleOutput,
        //        __out  PCONSOLE_SCREEN_BUFFER_INFO lpConsoleScreenBufferInfo
        //      );
        public boolean GetConsoleScreenBufferInfo(
                int in_hConsoleOutput,
                CONSOLE_SCREEN_BUFFER_INFO out_lpConsoleScreenBufferInfo);

        // DWORD WINAPI GetLastError(void);
        public int GetLastError();
    }
}

package com.stackoverflow.util;

import java.io.PrintStream;

import com.stackoverflow.util.Win32.Kernel32;

public class ConsoleUtil {
    public static void main(String[] args)
    throws Exception {
        System.out.print("abc");
        static_color_print(
                System.out, 
                "def", 
                Win32.CONSOLE_BACKGROUND_COLOR_RED, 
                Win32.CONSOLE_FOREGROUND_COLOR_BRIGHT_WHITE);
        System.out.print("def");
        System.out.println();
    }

    private static Win32.CONSOLE_SCREEN_BUFFER_INFO _static_console_screen_buffer_info = null; 

    public static void static_save_settings() {
        if (null == _static_console_screen_buffer_info) {
            _static_console_screen_buffer_info = new Win32.CONSOLE_SCREEN_BUFFER_INFO();
        }
        int stdout_handle = Kernel32.DLL.GetStdHandle(Win32.STD_OUTPUT_HANDLE);
        Kernel32.DLL.GetConsoleScreenBufferInfo(stdout_handle, _static_console_screen_buffer_info);
    }

    public static void static_restore_color()
    throws Exception {
        if (null == _static_console_screen_buffer_info) {
            throw new Exception("Internal error: Must save settings before restore");
        }
        int stdout_handle = Kernel32.DLL.GetStdHandle(Win32.STD_OUTPUT_HANDLE);
        Kernel32.DLL.SetConsoleTextAttribute(
                stdout_handle, 
                _static_console_screen_buffer_info.wAttributes);
    }

    public static void static_set_color(Short background_color, Short foreground_color) {
        int stdout_handle = Kernel32.DLL.GetStdHandle(Win32.STD_OUTPUT_HANDLE);
        if (null == background_color || null == foreground_color) {
            Win32.CONSOLE_SCREEN_BUFFER_INFO console_screen_buffer_info = 
                new Win32.CONSOLE_SCREEN_BUFFER_INFO();
            Kernel32.DLL.GetConsoleScreenBufferInfo(stdout_handle, console_screen_buffer_info);
            short current_bg_and_fg_color = console_screen_buffer_info.wAttributes;
            if (null == background_color) {
                short current_bg_color = (short) (current_bg_and_fg_color / 0x10);
                background_color = new Short(current_bg_color);
            }
            if (null == foreground_color) {
                short current_fg_color = (short) (current_bg_and_fg_color % 0x10);
                foreground_color = new Short(current_fg_color);
            }
        }
        short bg_and_fg_color = 
            (short) (background_color.shortValue() | foreground_color.shortValue());
        Kernel32.DLL.SetConsoleTextAttribute(stdout_handle, bg_and_fg_color);
    }

    public static<T> void static_color_print(
            PrintStream ostream, 
            T value, 
            Short background_color, 
            Short foreground_color)
    throws Exception {
        static_save_settings();
        try {
            static_set_color(background_color, foreground_color);
            ostream.print(value);
        }
        finally {
            static_restore_color();
        }
    }

    public static<T> void static_color_println(
            PrintStream ostream, 
            T value, 
            Short background_color, 
            Short foreground_color)
    throws Exception {
        static_save_settings();
        try {
            static_set_color(background_color, foreground_color);
            ostream.println(value);
        }
        finally {
            static_restore_color();
        }
    }
}

5

最简单的方法是在Cygwin控制台中运行您的程序(未修改)。

第二简单的方法是在普通Windows控制台中运行您的程序(也未修改),通过tee.exe(来自Cygwin或Git分发)将输出传输。Tee.exe将识别转义码并调用适当的WinAPI函数。

类似于:

java MyClass | tee.exe log.txt
java MyClass | tee.exe /dev/null

5
我创建了一个名为JCDP(Java Colored Debug Printer)的jar库。
对于Linux,它使用WhiteFang提到的ANSI转义码,但是使用单词抽象它们,而不是代码,这更加直观易懂。
对于Windows,它实际上包括JAnsi库,但在其上创建了一个抽象层,保持了为Linux创建的直观简单界面。
该库根据MIT许可证授权,所以请放心使用。
请查看JCDP的github存储库

3

转义序列必须由某个程序进行解释,才能将其转换为颜色。当使用命令行启动Java时,标准的CMD.EXE不支持此功能,因此Java也不支持。


3
如果你使用的是非Windows操作系统,那么终端应用程序很可能会执行转义序列解释。 - Jherico

2

请看这个:我使用了带有转义代码的ANSI值,可能在Windows命令提示符中无法正常工作,但在IDE和Unix shell中可以。你也可以查看'Jansi'库这里以获取Windows支持。

System.out.println("\u001B[35m" + "This text is PURPLE!" + "\u001B[0m");

1
尽管这段代码可能回答了问题,但提供有关它是如何解决问题的背景和/或原因将会增加答案的长期价值。请阅读此如何回答,以提供高质量的答案。 - thewaywewere

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