Java 控制台进度条

4,289 阅读2分钟

Java 控制台进度条

效果图

效果图

实现原理

\t TAB 制表符 \b BACK SPACE 退格符 \n New Line 换行符(本意:换一个新行,但列位置不变) \r Return 回车符 (本意:行位置不变,将列位置切换到本行首)

主要还是靠 \b 退格来实现的。

源码

主要用途:下载进度条,分批处理进度条,任务进度,加载进度等等。 可以把进度条的字符串传给前端,由前端显示进度。

话不多说,代码拿走。

import javax.annotation.concurrent.NotThreadSafe;

/**
 * 进度条工具
 * <p>
 * 这个进度条打印期间,其他控制台输出会影响最终结果
 * 所以做成单线程,阻塞的打印
 *
 * @author snx
 */
@NotThreadSafe
public class ProgressBar {


    /**
     * 当前进度
     */
    private int index;
    /**
     * 步长
     */
    private int step;
    /**
     * 进度条长度,总进度数值
     */
    private int barLength;

    /**
     * 是否初始化
     */
    private boolean hasInited = false;
    /**
     * 是否已经结束
     */
    private boolean hasFinished = false;
    /**
     * 进度条title
     */
    private String title;

    private static final char processChar = '█';
    private static final char waitChar = '─';


    private ProgressBar() {
        index = 0;
        step = 1;
        barLength = 100;
        title = "Progress:";
    }

    public static ProgressBar build() {
        return new ProgressBar();
    }

    public static ProgressBar build(int step) {
        ProgressBar progressBar = build();
        progressBar.step = step;
        return progressBar;
    }

    public static ProgressBar build(int index, int step) {
        ProgressBar progressBar = build(step);
        progressBar.index = index;
        return progressBar;
    }

    public static ProgressBar build(int index, int step, String title) {
        ProgressBar progressBar = build(index, step);
        progressBar.title = title;
        return progressBar;
    }

    private String generate(int num, char ch) {
        if (num == 0) return "";
        StringBuilder builder = new StringBuilder();
        for (int i = 0; i < num; i++) {
            builder.append(ch);
        }
        return builder.toString();
    }

    private String genProcess(int num) {
        return generate(num, processChar);
    }

    private String genWaitProcess(int num) {
        return generate(num, waitChar);
    }

    /**
     * 清空进度条
     */
    private void cleanProcessBar() {
        System.out.print(generate(barLength / step + 6, '\b'));
    }

    /**
     * 进度+1
     */
    public void process() {
        checkStatus();
        checkInit();
        cleanProcessBar();
        index++;
        drawProgressBar();
        checkFinish();
    }

    /**
     * 进度+指定数值
     *
     * @param process 指定数值
     */
    public void process(int process) {
        checkStatus();
        checkInit();
        cleanProcessBar();
        if (index + process >= barLength)
            index = barLength;
        else
            index += process;
        drawProgressBar();
        checkFinish();
    }

    /**
     * 步进
     */
    public void step() {
        checkStatus();
        checkInit();
        cleanProcessBar();
        if (index + step >= barLength)
            index = barLength;
        else
            index += step;
        drawProgressBar();
        checkFinish();
    }


    /**
     * 绘制进度条
     */
    public void drawProgressBar() {
        System.out.print(
                String.format(
                        "%3d%%├%s%s┤",
                        index,
                        genProcess(index / step),
                        genWaitProcess(barLength / step - index / step)
                )
        );
    }


    /**
     * 检查进度条状态
     * 已完成的进度条不可以继续执行
     */
    private void checkStatus() {
        if (hasFinished) throw XFSException.illegalStateException("进度条已经完成");
    }

    /**
     * 检查是否已经初始化
     */
    private void checkInit() {
        if (!hasInited) init();
    }


    /**
     * 检查是否已经完成
     */
    private void checkFinish() {
        if (hasFinished() && !hasFinished) finish();
    }

    /**
     * 是否已经完成进度条
     *
     * @return
     */
    public boolean hasFinished() {
        return index >= barLength;
    }

    /**
     * 初始化进度条
     */
    private void init() {
        checkStatus();
        System.out.print(title);
        System.out.print(String.format("%3d%%[%s%s]", index, genProcess(index / step), genWaitProcess(barLength / step - index / step)));
        hasInited = true;
    }

    /**
     * 结束进度条,由 checkFinish()调用
     */
    private void finish() {
        System.out.println();
        hasFinished = true;
    }

    /**
     * 间隔50ms 自动执行进度条
     *
     * @throws InterruptedException
     */
    public void printProgress() throws InterruptedException {
        init();
        do {
            step();
            Thread.sleep(50);
            index++;
        } while (index <= barLength);
        System.out.println();
    }
}


转载必须注明出处!!!!