• 控制台彩色输出


    今天在看另外一个优秀框架的源码的过程中,我发现了一个奇怪的现象,框架输出的内容居然自带颜色,这引起了我极大的好奇心。

    追根溯源,终于找到了Jansi。Jansi 是一个小型的 ASL 2.0 许可的 Java 库,它允许您使用 ANSI 转义序列来格式化您的控制台输出。

    下面分享一下Jansi的简单使用和我自己封装方法,以及随机输出颜色的文本的方法封装(这个我又强行一行代码实现了),先来一张效果图

    FunTester彩色输出

    依赖

    • Gradle
        // https://mvnrepository.com/artifact/org.fusesource.jansi/jansi
        implementation group: 'org.fusesource.jansi', name: 'jansi', version: '2.4.0'
    
    • Maven
    <!-- https://mvnrepository.com/artifact/org.fusesource.jansi/jansi -->
    <dependency>
        <groupId>org.fusesource.jansi</groupId>
        <artifactId>jansi</artifactId>
        <version>2.4.0</version>
    </dependency>
    
    

    Demo

    根据官方的最佳实践,的确啥也没找到,只有API Docs,只是简单列罗列,还不如写在源码中。下面是我找到的几个成功的例子:

    import com.funtester.frame.SourceCode;
    import org.fusesource.jansi.Ansi;
    
    public class Jnst extends SourceCode {
    
        public static void main(String[] args) {
    
            String blue = Ansi.ansi().fg(Ansi.Color.BLUE).a("蓝色FunTester").reset().toString();
            output(blue);
            String red = Ansi.ansi().fgRed().a("红色FunTester").reset().toString();
            output(red);
    
            String red1 = Ansi.ansi().fgBrightRed().a("红色FunTester").fgYellow().a("黄色FunTester").fgBrightGreen().a("绿色FunTester").reset().toString();
            output(red1);
    
            Ansi ansi = Ansi.ansi();
            Ansi a = ansi.fgRed().a("红色FunTester").fgBrightGreen().a("绿色FunTester");
            output(ansi);
            output("会打印绿色字符");
            ansi.reset();
            output(a);
            output("会打印正常颜色字符");
        }
    
    }
    
    

    三种设置颜色和内容的方法,大家去翻源码本质上也是各种封装。这里每一个ansi对象都有一个 private final StringBuilder builder;,如果大家想复用一个ansi对象,只要重置这个 private final StringBuilder builder;属性即可,重置的思路可以借助Java反射,言至于此,改天有机会再分享具体实现。

    其中Jansi支持的几种颜色如下:

            BLACK(0, "BLACK"),
            RED(1, "RED"),
            GREEN(2, "GREEN"),
            YELLOW(3, "YELLOW"),
            BLUE(4, "BLUE"),
            MAGENTA(5, "MAGENTA"),
            CYAN(6, "CYAN"),
            WHITE(7, "WHITE"),
            DEFAULT(9, "DEFAULT");
    

    封装

    下面是我的封装方法,比较简单,就是为了少些几行代码。我放弃了复用ansi对象的思路,因为反射执行效率太差了。

        public static String color(Ansi.Color color, Object o) {
            return ansi().fg(color).a(o.toString()).reset().toString();
        }
    
        public static void black(String str) {
            System.out.println(ansi().fgBlack().a(str));
        }
    
        public static void blue(Object o) {
            output(color(Ansi.Color.BLUE, o));
        }
    
        public static void red(Object o) {
            output(color(Ansi.Color.RED, o));
        }
    
        public static void green(Object o) {
            output(color(Ansi.Color.GREEN, o));
        }
    
        public static void yellow(Object o) {
            output(color(Ansi.Color.YELLOW, o));
        }
    
        public static void white(Object o) {
            output(color(Ansi.Color.WHITE, o));
        }
    
        public static void black(Object o) {
            output(color(Ansi.Color.BLACK, o));
        }
    
        public static void gyan(Object o) {
            output(color(Ansi.Color.CYAN, o));
        }
    
        public static void magenta(Object o) {
            output(color(Ansi.Color.MAGENTA, o));
        }
    
    

    拓展

    我拓展了一个将字符串里面的字符随机设置颜色(排除黑色,因为我常用的黑色背景)的方法,总体思路就是讲字符串拆成字符数组,然后逐个转换拼接。

    第一种方法:

        public static String rgb(String str) {
            char[] array = str.toCharArray();
            List<Ansi.Color> collect = Stream.of(Ansi.Color.values()).filter(v -> v != Ansi.Color.BLACK).collect(Collectors.toList());
            Ansi ansi = ansi();
            for (int i = 0; i < array.length; i++) {
                ansi.fg(random(collect)).a(array[i]);
            }
            return ansi.reset().toString();
        }
    

    当然我们也可以强行将这些代码写成一行:

        public static String rgb(String str) {
            return Stream.of(ArrayUtils.toObject(str.toCharArray())).map(f -> color(random(Stream.of(Ansi.Color.values()).filter(v -> v != Ansi.Color.BLACK).collect(Collectors.toList())), f)).collect(Collectors.joining());
        }
    
    

    用到不少Lambda语法,有兴趣的小伙伴可以看看Lambda语法,能省不少代码。

    欢迎关注FunTester,Have Fun ~ Tester !

  • 相关阅读:
    (todo)数组名 有存储空间吗?
    c和指针 指针数组 关于指针数组
    c面试题 来自android手机 1/6
    c 和指针 二维数组赋予一维数组指针 数组长度 数组与指针长度区别
    c语言优先级面试小结
    hxf 每晚 宏 不用大于小于 求大小
    DelphiX中的DXSprite单元中涉及到修改
    在java开发过程中,添加表时,需要配置一下的目录和文件。
    代码生成器cs的注册方法.
    将一个字符串映射为一个Delphi页面控件属性名
  • 原文地址:https://www.cnblogs.com/FunTester/p/15656887.html
Copyright © 2020-2023  润新知