wuxin0011`blog wuxin0011`blog
首页
  • 基础内容

    • HTML
    • CSS
    • JavaScript
  • 进阶

    • JavaScript教程
    • ES6 教程
    • Vue
    • React
    • Typescript
    • Git
  • 推荐阅读
  • java随笔
  • JVM (opens new window)
  • 分类
  • 标签
  • 归档
  • 学习
  • 面试
  • 心情杂货
  • 实用技巧
  • 友情链接
关于
  • git使用
  • docker部署项目
  • 错误收集
  • github-start
  • background-color
  • live-server
  • tampermonkey-script (opens new window)
  • leetcode-tool (opens new window)
  • 网站
  • 前端
  • 后端
  • Github Topic (opens new window)
GitHub (opens new window)

wuxin0011

懂得越多,懂得越少
首页
  • 基础内容

    • HTML
    • CSS
    • JavaScript
  • 进阶

    • JavaScript教程
    • ES6 教程
    • Vue
    • React
    • Typescript
    • Git
  • 推荐阅读
  • java随笔
  • JVM (opens new window)
  • 分类
  • 标签
  • 归档
  • 学习
  • 面试
  • 心情杂货
  • 实用技巧
  • 友情链接
关于
  • git使用
  • docker部署项目
  • 错误收集
  • github-start
  • background-color
  • live-server
  • tampermonkey-script (opens new window)
  • leetcode-tool (opens new window)
  • 网站
  • 前端
  • 后端
  • Github Topic (opens new window)
GitHub (opens new window)
  • 推荐阅读
  • Java

    • 常见集合总结
    • mybatis源码阅读
    • springboot启动原理
    • springcloud介绍
    • 分布式热点问题
    • Zookeeper介绍
    • RabbitMQ
    • tomcat源码阅读
    • 自定义输出内容颜色和背景
      • 思路来源
      • 自定义控制台输出颜色
        • Java简单封装自定义输出颜色
        • JS简单封装自定义输出颜色
        • C封装
      • color 命令
  • python

  • 后端
  • Java
wuxin0011
2023-10-04
目录

自定义输出内容颜色和背景

# 思路来源

最近体验了下blade (opens new window) ,一个轻量级MVC框架,看源码时候看到一个比较有意思的类 com.hellokaton.blade.kit.Ansi

package com.hellokaton.blade.kit;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import static com.hellokaton.blade.kit.SystemKit.isWindows;

/**
 *
 * @author dain
 */
public final class Ansi {

    // Color code strings from:
    // http://www.topmudsites.com/forums/mud-coding/413-java-ansi.html
    public static final String SANE = "\u001B[0m";

    public static final String HIGH_INTENSITY = "\u001B[1m";
    public static final String LOW_INTENSITY  = "\u001B[2m";

    public static final String ITALIC         = "\u001B[3m";
    public static final String UNDERLINE      = "\u001B[4m";
    public static final String BLINK          = "\u001B[5m";
    public static final String RAPID_BLINK    = "\u001B[6m";
    public static final String REVERSE_VIDEO  = "\u001B[7m";
    public static final String INVISIBLE_TEXT = "\u001B[8m";

    public static final String BLACK   = "\u001B[30m";
    public static final String RED     = "\u001B[31m";
    public static final String GREEN   = "\u001B[32m";
    public static final String YELLOW  = "\u001B[33m";
    public static final String BLUE    = "\u001B[34m";
    public static final String MAGENTA = "\u001B[35m";
    public static final String CYAN    = "\u001B[36m";
    public static final String WHITE   = "\u001B[37m";

    public static final String BACKGROUND_BLACK   = "\u001B[40m";
    public static final String BACKGROUND_RED     = "\u001B[41m";
    public static final String BACKGROUND_GREEN   = "\u001B[42m";
    public static final String BACKGROUND_YELLOW  = "\u001B[43m";
    public static final String BACKGROUND_BLUE    = "\u001B[44m";
    public static final String BACKGROUND_MAGENTA = "\u001B[45m";
    public static final String BACKGROUND_CYAN    = "\u001B[46m";
    public static final String BACKGROUND_WHITE   = "\u001B[47m";

    public static final Ansi HighIntensity = new Ansi(HIGH_INTENSITY);
    public static final Ansi Bold          = HighIntensity;
    public static final Ansi LowIntensity  = new Ansi(LOW_INTENSITY);
    public static final Ansi Normal        = LowIntensity;

    public static final Ansi Italic     = new Ansi(ITALIC);
    public static final Ansi Underline  = new Ansi(UNDERLINE);
    public static final Ansi Blink      = new Ansi(BLINK);
    public static final Ansi RapidBlink = new Ansi(RAPID_BLINK);

    public static final Ansi Black   = new Ansi(BLACK);
    public static final Ansi Red     = new Ansi(RED);
    public static final Ansi Green   = new Ansi(GREEN);
    public static final Ansi Yellow  = new Ansi(YELLOW);
    public static final Ansi Blue    = new Ansi(BLUE);
    public static final Ansi Magenta = new Ansi(MAGENTA);
    public static final Ansi Cyan    = new Ansi(CYAN);
    public static final Ansi White   = new Ansi(WHITE);

    public static final Ansi BgBlack   = new Ansi(BACKGROUND_BLACK);
    public static final Ansi BgRed     = new Ansi(BACKGROUND_RED);
    public static final Ansi BgGreen   = new Ansi(BACKGROUND_GREEN);
    public static final Ansi BgYellow  = new Ansi(BACKGROUND_YELLOW);
    public static final Ansi BgBlue    = new Ansi(BACKGROUND_BLUE);
    public static final Ansi BgMagenta = new Ansi(BACKGROUND_MAGENTA);
    public static final Ansi BgCyan    = new Ansi(BACKGROUND_CYAN);
    public static final Ansi BgWhite   = new Ansi(BACKGROUND_WHITE);

    final private String[] codes;
    final private String   codes_str;

    public Ansi(String... codes) {
        this.codes = codes;
        String _codes_str = "";
        for (String code : codes) {
            _codes_str += code;
        }
        codes_str = _codes_str;
    }

    public Ansi and(Ansi other) {
        List<String> both = new ArrayList<String>();
        Collections.addAll(both, codes);
        Collections.addAll(both, other.codes);
        return new Ansi(both.toArray(new String[]{}));
    }

    public String colorize(String original) {
        return codes_str + original + SANE;
    }

    public String format(String template, Object... args) {
        if (isWindows()) {
            if (null == args || args.length == 0) {
                return template;
            }
            return String.format(template, args);
        }
        String text = (null == args || args.length == 0) ? template : String.format(template, args);
        return colorize(text);
    }

}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109

没错,就是这个类,能控制输出字体颜色,但是没有自定义简单颜色类型,我很好奇这样就能自定义输出内容背景 和 字体样式 ?测试了下,的确可以,本着搞清楚原因去看了源码中

给出的链接地址 http://www.topmudsites.com/forums/mud-coding/413-java-ansi.html

# 自定义控制台输出颜色

Java中自带两种输出流能够输出不同样式

System.out.println(System.getProperty("java.version"));
System.err.println(System.getProperty("java.version"));
1
2

java-version-color

或者浏览器中默认输出样式

console.log(window.navigator.appVersion)
console.warn(window.navigator.appVersion)
console.info(window.navigator.appVersion)
console.error(window.navigator.appVersion)
1
2
3
4

js-version-color

当然浏览器console 对象支持自定义背景色。


console.log("%c%s","background-color:teal;color:#fff;padding:3px;font-size:50px;font-family:'宋体',","Hello world")

1
2
3

js-print-version-01.png

但是Java不支持这种写法,但是可以通过 ANSI (opens new window) 编码方式控制。

# Java简单封装自定义输出颜色

参考blade中源码,发现其中样式还是不够灵活,查了下ANSI表现形式, 发现不局限于语言,意思就是任何语言都支持这种写法。因此就十分有必要了解下了。

package com.wuxin;


/**
 * @author: wuxin0011
 * @Description:
 */
public class CustomColor {

    public static void main(String[] args) throws Exception {
        testColor();
    }


    public static void testColor() throws Exception {
        for (int i = 0; i < 10; i++) {
            Thread.sleep(200);
            System.out.println(backgroundColor("java.version=", System.getProperty("java.version")));
        }
        System.out.println("==========================");
        for (int i = 0; i < 10; i++) {
            Thread.sleep(200);
            System.out.println(fontColor("java.version=", System.getProperty("java.version")));
        }
        System.out.println("==========================");
        for (int i = 0; i < 10; i++) {
            Thread.sleep(200);
            System.out.println(colorTemplate(new MyColor(), new MyColor(), "java.version=", System.getProperty("java.version")));
        }
        Thread.sleep(200);
        System.out.println("==============custom color ============");
        System.out.println(colorTemplate(new MyColor(0, 0, 0), new MyColor(255, 255, 255), "java.version=", System.getProperty("java.version")));
    }

    private static final int RGB_VALUE_MAX = 255;
    private static final int BACKGROUND_COLOR = 48;
    private static final int FONT_COLOR = 38;
    private static final String CLEAR_COLOR = "\u001B[0m";


    public static class MyColor {
        public int R;
        public int G;
        public int L;

        public MyColor(int r, int g, int l) {
            this.R = r;
            this.G = g;
            this.L = l;
        }

        public MyColor() {
            this.R = randomColorValue();
            this.G = randomColorValue();
            this.L = randomColorValue();
        }
    }


    public static int randomColorValue() {
        return (int) Math.floor(Math.random() * RGB_VALUE_MAX);
    }

    public static String fontColor(String... content) {
        int R = randomColorValue();
        int G = randomColorValue();
        int L = randomColorValue();
        return fontColor(R, G, L, content);
    }

    public static String fontColor(MyColor myColor, String... content) {
        return fontColor(myColor.R, myColor.G, myColor.L, content);
    }

    public static String fontColor(int R, int G, int L, String... content) {
        return colorTemplate(FONT_COLOR, R, G, L, content);
    }

    public static String backgroundColor(String... content) {
        int R = randomColorValue();
        int G = randomColorValue();
        int L = randomColorValue();
        return backgroundColor(R, G, L, content);
    }

    public static String backgroundColor(MyColor myColor, String... content) {
        return backgroundColor(myColor.R, myColor.G, myColor.L, content);
    }

    public static String backgroundColor(int R, int G, int L, String... content) {
        return colorTemplate(BACKGROUND_COLOR, R, G, L, content);
    }


    public static String colorTemplate(int type, int R, int G, int L, String... content) {
        valid(R, G, L);
        StringBuilder s = new StringBuilder();
        for (String s1 : content) {
            s.append(s1);
        }
        return String.format("\u001B[%d;2;%d;%d;%dm%s\u001B[0m", type, R, G, L, s.toString());
    }

    public static String colorTemplate(int R1, int G1, int L1, int R2, int G2, int L2, String... content) {
        valid(R1, G1, L1, R2, G2, L2);
        StringBuilder s = new StringBuilder();
        for (String s1 : content) {
            s.append(s1);
        }
        return String.format("\u001B[%s;2;%d;%d;%dm\u001B[%s;2;%d;%d;%dm%s\u001B[0m", BACKGROUND_COLOR, R1, G1, L1, FONT_COLOR, R2, G2, L2, s.toString());
    }

    public static String colorTemplate(MyColor bc, MyColor fc, String... content) {
        return colorTemplate(bc.R, bc.G, bc.L, fc.R, fc.G, fc.L, content);
    }


    public static void valid(MyColor... myColors) {
        for (MyColor myColor : myColors) {
            valid(myColor.R, myColor.G, myColor.L);
        }
    }

    public static void valid(int... ints) {
        for (int result : ints) {
            if (result > RGB_VALUE_MAX) {
                throw new RuntimeException("color value max is " + RGB_VALUE_MAX);
            }
        }
    }
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132

关于\u001B[%s;2;%d;%d;%dm%s\u001B[0m含义

  • \u001B 开启颜色模式

  • %s表示是字体颜色(38)还是背景颜色(48)

  • 2 是启用rgb模式,用5表示启用#000 这种形式颜色,上面没有封装#xxx这种形式

  • 三个%d分别对应 rgb三个位置数值

  • %s 表示输出内容,就是你传入字符串

  • \u001B[0m表示还原,这样就不影响后续输出了

执行测试结果

java-version-print-02

在Linux中测试

java-version-print-02

# JS简单封装自定义输出颜色

function backgroundColor(...str){
	
	function colorRandom(l=255){
		return Math.floor(Math.random()*l)
	}

	let r = colorRandom();
	let g = colorRandom();
	let l = colorRandom();
	let printColor = (...m)=>console.log(`\u001B[48;2;${r};${g};${l}m ${m} \u001B[0m`)
    printColor(str)

}


function fontColor(...str){
	function colorRandom(l=255){
		return Math.floor(Math.random()*l)
	}

	let r = colorRandom();
	let g = colorRandom();
	let l = colorRandom();
	let printColor = (...m)=>console.log(`\u001B[38;2;${r};${g};${l}m ${m} \u001B[0m`)
    printColor(str)
}

Array.from({length:10}).forEach(()=>{
    fontColor("hello world")
    console.log('=============================')
    backgroundColor("hello world")
})
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32

在浏览器中执行就是代码测试

执行测试结果

测试浏览器是Edge浏览器

edge-print-color.png

经测试在firefox中测试无效!说明兼容性不是很好

firefox-print-fail.png

简单处理下兼容性问题

function isFirefox() {
    // 顺便兼容喜爱node环境
	try {
		if (typeof window !== undefined) {
			return window.navigator.userAgent.indexOf("Firefox") !== -1;
		}
	} catch (error) {
        // ignore 
	}
	return false
}
function backgroundColor(...str) {

	function colorRandom(l = 255) {
		return Math.floor(Math.random() * l)
	}

	let r = colorRandom();
	let g = colorRandom();
	let l = colorRandom();
	let printColor = (...m) => {
		if (isFirefox()) {
			console.log(`%c${m}`, `background-color: rgb(${r}, ${g}, ${l})`)
		}
		else {
			console.log(`\u001B[48;2;${r};${g};${l}m ${m} \u001B[0m`)
		}
	}
	printColor(str)

}


function fontColor(...str) {
	function colorRandom(l = 255) {
		return Math.floor(Math.random() * l)
	}

	let r = colorRandom();
	let g = colorRandom();
	let l = colorRandom();
	let printColor = (...m) => {
		if (isFirefox()) {
			console.log(`%c${m}`, `color: rgb(${r}, ${g}, ${l})`)
		} else {
			console.log(`\u001B[38;2;${r};${g};${l}m ${m} \u001B[0m`)
		}
	}
	return printColor(str)
}


Array.from({ length: 10 }).forEach(() => {
	fontColor("hello world")
	console.log('=============================')
	backgroundColor("hello world")
})

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58

firefox-print-success.png

node 中执行

node-print-color.png

# C封装

作为万物起源,C当然也支持了!



#include <stdio.h>
#include <stdlib.h>
#include <time.h>

#define COLOR_MAX 255
#define COLOR_BACKGROUND 48
#define COLOR_FONT 38


/*define */
typedef struct CustomColor
{

		int R;
		int G;
		int L;

}CustomColor;



void backgroundColorPrint(int R,int G,int L,char* ch);
void colorPrintTemplate(int type ,int R,int G,int L,char* ch);
void fontColorAndBackgroundTemplate(int R,int G,int L,int R1,int G1,int L1,char* ch);
void backgroundColorPrint(int R,int G,int L,char* ch);
void fontColorPrint(int R,int G,int L,char* ch);
int randomValue();
bool valid(int c);
CustomColor genCustomColor(int R,int G,int L);
void printRGL(int R,int G,int L);
void warning(char* ch);
void info(char* ch);
void error(char* ch);
void success(char* ch);

/******************************************************************************************/



int main(){
	char ch[] = "c language print color !";
	
	warning(ch);
	info(ch);
	error(ch);
	success(ch);


	for(int i = 0;i<30;i++){
		int R = randomValue();
		int G = randomValue();
		int L = randomValue();
		int R1 = randomValue();
		int G1 = randomValue();
		int L1 = randomValue();
		// printRGL(R,G,L);
		backgroundColorPrint(R,G,L,ch);
		fontColorPrint(R1,G1,L1,ch);
	}
	return 0;
}





int randomValue(){
	return rand() % COLOR_MAX;
}

bool valid(int c){
	return 0<=c && c<=COLOR_MAX;
}



void colorPrintTemplate(int type ,int R,int G,int L,char* ch){
	if( !(valid(R) && valid(G) && valid(L))){
		// if valid fail use default print
		printf("%s\n",ch);
		return;
	}
	printf("\u001B[%d;2;%d;%d;%dm %s\u001B[0m\n",type,R,G,L,ch);
}

void fontColorAndBackgroundTemplate(int R,int G,int L,int R1,int G1,int L1,char* ch){
	if( !(valid(R) && valid(G) && valid(L) && valid(R1) && valid(G1) && valid(L1))){
		// if valid fail use default print
		printf("%s\n",ch);
		return;
	}
	printf("\u001B[%d;2;%d;%d;%dm\u001B[%d;2;%d;%d;%dm%s\u001B[0m\n",COLOR_BACKGROUND,R,G,L,COLOR_FONT,R1,G1,L1,ch);
}



void backgroundColorPrint(int R,int G,int L,char* ch){
  colorPrintTemplate(COLOR_BACKGROUND,R,G,L,ch);
}

void fontColorPrint(int R,int G,int L,char* ch){
  colorPrintTemplate(COLOR_FONT,R,G,L,ch);
}

void printRGL(int R,int G,int L){
	printf("R = %d,G = %d,L = %d\n",R,G,L);
}


CustomColor genCustomColor(int R,int G,int L){
	CustomColor cs = {R,G,L};
	return cs;
}



void warning(char* ch){
  fontColorAndBackgroundTemplate(51, 43, 0,181, 157, 38,ch);
}

void error(char* ch){
  fontColorAndBackgroundTemplate(41, 0, 0,255, 128, 95,ch);
}

void info(char* ch){
  fontColorAndBackgroundTemplate(0,0,0,255,255,255,ch);
}

void success(char* ch){
  fontColorAndBackgroundTemplate(68, 144, 54,255,255,255,ch);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133

测试结果

c-success.png

# color 命令

在 window cmd 控制台中有这样一个命令 color

cmd-00

当然也可以通过属性调整

cmd-01

编辑 (opens new window)
#随笔
上次更新: 2024-05-21, 09:50:09
tomcat源码阅读
python 入门

← tomcat源码阅读 python 入门→

最近更新
01
LeetCode刷题工具之本地对拍
04-04
02
sublime对应语言模板使用技巧
02-28
03
经典字符串匹配算法
02-05
更多文章>
Theme by Vdoing | Copyright © 2020-2024 wuxin0011 | MIT License
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式