自定义输出内容颜色和背景
# 思路来源
最近体验了下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);
}
}
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"));
2
或者浏览器中默认输出样式
console.log(window.navigator.appVersion)
console.warn(window.navigator.appVersion)
console.info(window.navigator.appVersion)
console.error(window.navigator.appVersion)
2
3
4
当然浏览器console
对象支持自定义背景色。
console.log("%c%s","background-color:teal;color:#fff;padding:3px;font-size:50px;font-family:'宋体',","Hello world")
2
3
但是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);
}
}
}
}
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
表示还原,这样就不影响后续输出了
执行测试结果
在Linux中测试
# 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")
})
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浏览器
经测试在firefox
中测试无效!说明兼容性不是很好
简单处理下兼容性问题
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")
})
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
node 中执行
# 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);
}
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
测试结果
# color 命令
在 window cmd
控制台中有这样一个命令 color
当然也可以通过属性调整