首页 > 编程语言 >JAVA控制台打印进度条工具类

JAVA控制台打印进度条工具类

时间:2023-07-14 15:48:04浏览次数:33  
标签:JAVA BigDecimal 进度条 MILLIS long PER private 控制台

有些时候我们需要写批处理任务,但是我们需要监控处理的进度,这个时候我们需要写一个计数器在统计,获取还需要好看一些。工具类代码没有第三方依赖,拷贝了网上其他出处的代码加以修改,因为源代码只能处理100条标准的数据,该进度条,不管你有多少条数据都可以正确显示如下图:
image
image
使用方式也是很简单:

public static void main(String[] args) throws Exception {
        long dataLength = 1330;
        ProgressBar bar = ProgressBar.build(dataLength);
        for (int i = 0; i < dataLength; i++) {
            Thread.sleep(10);
            bar.process();
        }
    }
	```

工具类代码如下:
```java
package tool.util;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.NumberFormat;
import java.util.Objects;

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


    /**
     * 进度条长度
     */
    private int BAR_LENGTH = 35;

    /**
     * 进度条缩放比例
     */
    private BigDecimal resizeRate;

    /**
     * 总数据长度
     */
    private long dataCount;

    /**
     * 当前进度
     */
    private volatile long completeCount;

    /**
     * 完成进度在进度条中的数量
     */
    private volatile int completeBarCount;

    /**
     * 完成进度百分比
     */
    private volatile String completePercent;

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

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

    public static final long MILLIS_PER_SECOND = 1000;
    public static final long MILLIS_PER_MINUTE = 60 * MILLIS_PER_SECOND;
    public static final long MILLIS_PER_HOUR = 60 * MILLIS_PER_MINUTE;

    public static final long MILLIS_PER_DAY = 24 * MILLIS_PER_HOUR;

    private long startTime;
    private long endTime;
    private String content;


    private ProgressBar() {
        resizeRate = new BigDecimal(BAR_LENGTH).divide(new BigDecimal(100), 2, RoundingMode.HALF_UP);
    }

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



    public static ProgressBar build(long dataCount) {
        return build(dataCount, 0, "Progress");
    }

    public static ProgressBar build(long dataCount, String title) {
        return build(dataCount, 0, title);
    }

    public static ProgressBar build(long dataCount, long completeCount, String title) {
        ProgressBar progressBar = build();
        progressBar.dataCount = dataCount;
        progressBar.completeCount = completeCount;
        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() {
        if(Objects.nonNull(content)) {
//            System.out.print(generate(content.length(), '\b'));
        }
        System.out.print('\r');
    }

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

    private void doProcess() {
        completeCount++;
        BigDecimal completeBarRate = getCompleteRate();
        completeBarCount = genCompleteBarCount(completeBarRate);
        completePercent = genCompletePercent(completeBarRate);
    }

    private int genCompleteBarCount(BigDecimal completeBarRate) {
        BigDecimal completeBarCount = BigDecimal.ZERO;
        if(completeCount > 0 && dataCount > 0) {
            completeBarCount = completeBarRate
                    .multiply(new BigDecimal("100"))
                    .multiply(resizeRate);
        }
        return completeBarCount.intValue();

    }

    private String genCompletePercent(BigDecimal completeBarRate) {
        NumberFormat percentInstance = NumberFormat.getPercentInstance();
        percentInstance.setMaximumFractionDigits(2);
        return percentInstance.format(completeBarRate);
    }

    private BigDecimal getCompleteRate() {
        BigDecimal completeBarRate = BigDecimal.ZERO;
        if(completeCount > 0 && dataCount > 0) {
            completeBarRate = new BigDecimal(completeCount).divide(new BigDecimal(dataCount), 4, RoundingMode.HALF_UP);
        }
        return completeBarRate;
    }




    private String genDurationStr() {
        long days         = 0;
        long hours        = 0;
        long minutes      = 0;
        long seconds      = 0;
        long milliseconds = System.currentTimeMillis() - startTime;

        days = milliseconds / MILLIS_PER_DAY;
        milliseconds = milliseconds - (days * MILLIS_PER_DAY);
        hours = milliseconds / MILLIS_PER_HOUR;
        milliseconds = milliseconds - (hours * MILLIS_PER_HOUR);
        minutes = milliseconds / MILLIS_PER_MINUTE;
        milliseconds = milliseconds - (minutes * MILLIS_PER_MINUTE);
        seconds = milliseconds / MILLIS_PER_SECOND;
        milliseconds = milliseconds - (seconds * MILLIS_PER_SECOND);
        StringBuilder sb = new StringBuilder();
        if(days > 0) {
            sb.append(days).append('天');
        }
        if(hours > 0) {
            sb.append(hours).append("小时");
        }
        if(minutes > 0) {
            sb.append(minutes).append("分钟");
        }
        if(seconds > 0) {
            sb.append(seconds).append('秒');
        }
        if(milliseconds > 0) {
            sb.append(milliseconds).append("毫秒");
        }
        return sb.toString();
    }

    /**
     * 绘制进度条
     */
    private void drawProgressBar() {
        checkStatus();
        content = String.format(
                "%s: %7s├%s%s┤%s",
                title,
                completePercent,
                genProcess(completeBarCount),
                genWaitProcess(BAR_LENGTH - completeBarCount),
                genDurationStr()
        );
        System.out.print(content);
    }


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

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


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

    /**
     * 是否已经完成进度条
     *
     * @return
     */
    private boolean hasFinished() {
        return completeCount >= dataCount;
    }

    /**
     * 初始化进度条
     */
    private void init() {
        hasInited = true;
        startTime = System.currentTimeMillis();
    }

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

}

标签:JAVA,BigDecimal,进度条,MILLIS,long,PER,private,控制台
From: https://www.cnblogs.com/charles69/p/17553842.html

相关文章

  • iris框架java
    如何使用Iris框架进行Java开发简介Iris是一个基于Java的高性能Web框架,它提供了简洁易用的API,使得开发者可以快速构建Web应用程序。本文将介绍如何使用Iris框架进行Java开发,并指导刚入行的开发者实现一个简单的示例。整体流程下面是使用Iris框架进行Java开......
  • 关于Java类加载器的一些理解
    Java中,每个类都可以获得对应自己类的Class对象,这是因为Object类中有publicfinalnativegetClass()方法,Class对象是由类加载器根据类字节码生成的,是反射机制必不可少的部分。类加载器中,主要的方法有protectedClassloadClass(Stringname,booleanresolve)和protectedClassf......
  • 老杜 JavaWeb 讲解(十) —— HttpServletRequest接口源码分析
    (十二)HttpServletRequest接口源码分析对应视频:21-HttpServletRequest接口12.1介绍HttpServletRequest是一个接口,全限定名称:jakarta.servlet.http.HttpServletRequestHttpServletRequest接口是Servlet规范中的一员。HttpServletRequest接口的父接口:ServletRequest......
  • Java优化递归查询Mysql节点树数据
    示例目前有一个功能:任务计划管理,必然存在多级子任务的父子级关系,每个任务还会存在其它数据的关联表。mysql无法一次性递归查出想要的数据结构,想必很多人都会是通过根目录递归查询数据库的方式查出树结构数据。如果节点数较多,就会造成大量请求Mysql查询,效率会很低。那么如......
  • 【AGC】删除控制台应用重建报错url is null问题
    ​【关键字】AGC、agconnect-services.json、InvalidParameterException 【问题描述】有开发者反馈在删除了AppGalleryConnect中某个应用及其对应的项目,再重新创建相同的应用(包名一致),并且重新下载agconnect-services.json到项目中,应用会因为com.huawei.agconnect闪退。报错......
  • JAVA设计模式之责任链模式
    设计模式设计模式(DesignPattern)是前辈们对代码开发经验的总结,是解决特定问题的一系列套路。它不是语法规定,而是一套用来提高代码可复用性、可维护性、可读性、稳健性以及安全性的解决方案。总体来说设计模式分为三大类:创建型模式,共五种:工厂方法模式、抽象工厂模式、单例模式、......
  • java 抛出异常后继续执行
    Java抛出异常后继续执行的实现方法作为一名经验丰富的开发者,我将为你介绍如何在Java中实现“抛出异常后继续执行”的方法。在实现之前,我们先来了解一下整个过程的流程,然后逐步进行实现。整体流程步骤描述步骤1执行可能会抛出异常的代码步骤2捕获并处理异常......
  • java 判断字符串内容是utf-8还是utf8mb4
    判断字符串内容是UTF-8还是UTF8MB4的方法概述在Java中,判断字符串内容是UTF-8还是UTF8MB4可以通过检查字符编码范围来实现。UTF-8使用1到4个字节表示一个字符,而UTF8MB4使用1到4个字节表示一个字符。下面将介绍整个流程和每一步需要做的事情。流程步骤描述1.将字符串转......
  • java 判断以逗号分割的字符串
    Java判断以逗号分割的字符串简介在Java中,判断以逗号分割的字符串可以使用split方法将字符串分割成多个子字符串,然后逐个判断每个子字符串是否满足特定条件。本文将介绍如何使用Java实现这一功能。流程图步骤描述步骤1通过split方法将字符串分割成多个子字符串步......
  • java 判断一个对象中是否存在重复的字段
    Java判断一个对象中是否存在重复的字段1.流程以下是判断一个对象中是否存在重复字段的流程:步骤描述1获取对象的所有字段2遍历字段,将字段名存入一个集合3判断集合的大小与字段数是否相等,若不相等则存在重复字段2.代码实现下面是每个步骤所需要完成的代......