All Downloads are FREE. Search and download functionalities are using the official Maven repository.

me.tongfei.progressbar.ProgressBar Maven / Gradle / Ivy

The newest version!
package me.tongfei.progressbar;

import me.tongfei.progressbar.wrapped.*;

import static me.tongfei.progressbar.Util.createConsoleConsumer;

import java.io.*;
import java.text.DecimalFormat;
import java.time.Duration;
import java.time.Instant;
import java.time.temporal.ChronoUnit;
import java.util.Arrays;
import java.util.Iterator;
import java.util.Spliterator;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import java.util.stream.BaseStream;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;

/**
 * A console-based progress bar with minimal runtime overhead.
 * @author Tongfei Chen
 */
public class ProgressBar implements AutoCloseable {

    private final ProgressState progress;
    private final ProgressUpdateAction action;
    private final ScheduledFuture scheduledTask;

    /**
     * Creates a progress bar with the specific taskName name and initial maximum value.
     * @param task Task name
     * @param initialMax Initial maximum value
     */
    public ProgressBar(String task, long initialMax) {
        this(
                task, initialMax, 1000, false, false,
                System.err, ProgressBarStyle.COLORFUL_UNICODE_BLOCK,
                "", 1L, false, null,
                ChronoUnit.SECONDS, 0L, Duration.ZERO
        );
    }

    /**
     * Creates a progress bar with the specific taskName name, initial maximum value,
     * customized update interval (default 1000 ms), the PrintStream to be used, and output style.
     * @param task Task name
     * @param initialMax Initial maximum value
     * @param updateIntervalMillis Update interval (default value 1000 ms)
     * @param continuousUpdate Rerender every time the update interval happens regardless of progress count.
     * @param style Draw style
     * @param showSpeed Should the calculated speed be displayed
     * @param speedFormat Speed number format
     * @deprecated Use {@link ProgressBarBuilder} instead.
     */
    public ProgressBar(
            String task,
            long initialMax,
            int updateIntervalMillis,
            boolean continuousUpdate,
            boolean clearDisplayOnFinish,
            PrintStream os,
            ProgressBarStyle style,
            String unitName,
            long unitSize,
            boolean showSpeed,
            DecimalFormat speedFormat,
            ChronoUnit speedUnit,
            long processed,
            Duration elapsed
    ) {
        this(task, initialMax, updateIntervalMillis, continuousUpdate, clearDisplayOnFinish, processed, elapsed,
                new DefaultProgressBarRenderer(
                        style, unitName, unitSize,
                        showSpeed, speedFormat, speedUnit,
                        true, Util::linearEta
                ),
                createConsoleConsumer(os)
        );
    }

    /**
     * Creates a progress bar with the specific name, initial maximum value, customized update interval (default 1s),
     * and the provided progress bar renderer ({@link ProgressBarRenderer}) and consumer ({@link ProgressBarConsumer}).
     * @param task Task name
     * @param initialMax Initial maximum value
     * @param updateIntervalMillis Update time interval (default value 1000ms)
     * @param continuousUpdate Rerender every time the update interval happens regardless of progress count.
     * @param processed Initial completed process value
     * @param elapsed Initial elapsedBeforeStart second before
     * @param renderer Progress bar renderer
     * @param consumer Progress bar consumer
     * @deprecated Use {@link ProgressBarBuilder} instead. Will be private in future versions.
     */
    public ProgressBar(
            String task,
            long initialMax,
            int updateIntervalMillis,
            boolean continuousUpdate,
            boolean clearDisplayOnFinish,
            long processed,
            Duration elapsed,
            ProgressBarRenderer renderer,
            ProgressBarConsumer consumer
    ) {
        this.progress = new ProgressState(task, initialMax, processed, elapsed);
        this.action = new ProgressUpdateAction(progress, renderer, consumer, continuousUpdate, clearDisplayOnFinish);
        scheduledTask = Util.executor.scheduleAtFixedRate(
                action, 0, updateIntervalMillis, TimeUnit.MILLISECONDS
        );
    }

    /**
     * Advances this progress bar by a specific amount.
     * @param n Step size
     */
    public ProgressBar stepBy(long n) {
        progress.stepBy(n);
        return this;
    }

    /**
     * Advances this progress bar to the specific progress value.
     * @param n New progress value
     */
    public ProgressBar stepTo(long n) {
        boolean back = n < progress.current;
        progress.stepTo(n);
        if (back) action.forceRefresh();  // fix #124
        return this;
    }

    /**
     * Advances this progress bar by one step.
     */
    public ProgressBar step() {
        progress.stepBy(1);
        return this;
    }

    /**
     * Gives a hint to the maximum value of the progress bar.
     * @param n Hint of the maximum value. A value of -1 indicates that the progress bar is indefinite.
     */
    public ProgressBar maxHint(long n) {
        if (n < 0)
            progress.setAsIndefinite();
        else {
            progress.setAsDefinite();
            progress.maxHint(n);
        }
        return this;
    }

    /**
     * Pauses this current progress.
     */
    public ProgressBar pause() {
        progress.pause();
        return this;
    }

    /**
     * Resumes this current progress.
     */
    public ProgressBar resume() {
        progress.resume();
        return this;
    }

    /** Resets the progress bar to its initial state (where progress equals to 0). */
    public ProgressBar reset() {
        progress.reset();
        action.forceRefresh();  // force refresh, fixing #124
        return this;
    }

    /**
     * 

Stops this progress bar, effectively stops tracking the underlying process.

*

Implements the {@link AutoCloseable} interface which enables the try-with-resource * pattern with progress bars.

* @since 0.7.0 */ @Override public void close() { scheduledTask.cancel(false); progress.kill(); try { Util.executor.schedule(action, 0, TimeUnit.NANOSECONDS).get(); } catch (InterruptedException | ExecutionException e) { /* NOOP */ } } /** * Sets the extra message at the end of the progress bar. * @param msg New message */ public ProgressBar setExtraMessage(String msg) { progress.setExtraMessage(msg); return this; } /** * Returns the current progress. */ public long getCurrent() { return progress.getCurrent(); } /** * Returns the maximum value of this progress bar. */ public long getMax() { return progress.getMax(); } public long getStart() { return progress.getStart(); } /** * Returns the progress normalized to the interval [0, 1]. */ public double getNormalizedProgress() { return progress.getNormalizedProgress(); } /** * Returns the instant when the progress bar started. * If a progress bar is resumed after a pause, it returns the instant when the progress was resumed. */ public Instant getStartInstant() { return progress.startInstant; } /** * Returns the duration that this progress bar has been running before it was resumed. * If a progress bar starts afresh, it should return zero. */ public Duration getElapsedBeforeStart() { return progress.getElapsedBeforeStart(); } /** * Returns the duration that this progress bar has been running after it was resumed. * If a progress bar has not been paused before, it should return the total duration starting from creation. */ public Duration getElapsedAfterStart() { return progress.getElapsedAfterStart(); } /** * Returns the total duration that this progress bar has been running from start, * excluding the period when it has been paused. */ public Duration getTotalElapsed() { return progress.getTotalElapsed(); } /** * Returns the name of this task. */ public String getTaskName() { return progress.getTaskName(); } /** * Returns the extra message at the end of the progress bar. */ public String getExtraMessage() { return progress.getExtraMessage(); } /** Checks if the progress bar is indefinite, i.e., its maximum value is unknown. */ public boolean isIndefinite() { return progress.indefinite; } /** * Prompts the progress bar to refresh. Normally a user should not call this function. */ public void refresh() { action.refresh(); } // STATIC WRAPPER METHODS /** * Wraps an iterator so that when iterated, a progress bar is shown to track the traversal progress. * @param it Underlying iterator * @param task Task name */ public static Iterator wrap(Iterator it, String task) { return wrap(it, new ProgressBarBuilder().setTaskName(task).setInitialMax(-1) ); // indefinite progress bar } /** * Wraps an iterator so that when iterated, a progress bar is shown to track the traversal progress. * @param it Underlying iterator * @param pbb Progress bar builder */ public static Iterator wrap(Iterator it, ProgressBarBuilder pbb) { return new ProgressBarWrappedIterator<>(it, pbb.build()); } /** * Wraps an {@link Iterable} so that when iterated, a progress bar is shown to track the traversal progress. *

* Sample usage: {@code * for (T x : ProgressBar.wrap(collection, "Traversal")) { ... } * } *

* @param ts Underlying iterable * @param task Task name */ public static Iterable wrap(Iterable ts, String task) { return wrap(ts, new ProgressBarBuilder().setTaskName(task)); } /** * Wraps an {@link Iterable} so that when iterated, a progress bar is shown to track the traversal progress. * For this function the progress bar can be fully customized by using a {@link ProgressBarBuilder}. * @param ts Underlying iterable * @param pbb An instance of a {@link ProgressBarBuilder} */ public static Iterable wrap(Iterable ts, ProgressBarBuilder pbb) { if (!pbb.initialMaxIsSet()) pbb.setInitialMax(Util.getSpliteratorSize(ts.spliterator())); return new ProgressBarWrappedIterable<>(ts, pbb); } /** * Wraps an {@link InputStream} so that when read, a progress bar is shown to track the reading progress. * @param is Input stream to be wrapped * @param task Name of the progress */ public static InputStream wrap(InputStream is, String task) { ProgressBarBuilder pbb = new ProgressBarBuilder().setTaskName(task); return wrap(is, pbb); } /** * Wraps an {@link InputStream} so that when read, a progress bar is shown to track the reading progress. * For this function the progress bar can be fully customized by using a {@link ProgressBarBuilder}. * @param is Input stream to be wrapped * @param pbb An instance of a {@link ProgressBarBuilder} */ public static InputStream wrap(InputStream is, ProgressBarBuilder pbb) { if (!pbb.initialMaxIsSet()) pbb.setInitialMax(Util.getInputStreamSize(is)); return new ProgressBarWrappedInputStream(is, pbb.build()); } /** * Wraps an {@link OutputStream} so that when written, a progress bar is shown to track the writing progress. * @param os Output stream to be wrapped * @param task Name of the progress */ public static OutputStream wrap(OutputStream os, String task) { ProgressBarBuilder pbb = new ProgressBarBuilder().setTaskName(task); return wrap(os, pbb); } /** * Wraps an {@link OutputStream} so that when written, a progress bar is shown to track the writing progress. * For this function the progress bar can be fully customized by using a {@link ProgressBarBuilder}. * @param os Output stream to be wrapped * @param pbb An instance of a {@link ProgressBarBuilder} */ public static OutputStream wrap(OutputStream os, ProgressBarBuilder pbb) { return new ProgressBarWrappedOutputStream(os, pbb.build()); } /** * Wraps a {@link Reader} so that when read, a progress bar is shown to track the reading progress. * @param reader Reader to be wrapped * @param task Name of the progress */ public static Reader wrap(Reader reader, String task) { ProgressBarBuilder pbb = new ProgressBarBuilder().setTaskName(task); return wrap(reader, pbb); } /** * Wraps a {@link Reader} so that when read, a progress bar is shown to track the reading progress. * For this function the progress bar can be fully customized by using a {@link ProgressBarBuilder}. * @param reader Reader to be wrapped * @param pbb An instance of a {@link ProgressBarBuilder} */ public static Reader wrap(Reader reader, ProgressBarBuilder pbb) { return new ProgressBarWrappedReader(reader, pbb.build()); } /** * Wraps a {@link Writer} so that when written, a progress bar is shown to track the writing progress. * @param writer Writer to be wrapped * @param task Name of the progress */ public static Writer wrap(Writer writer, String task) { ProgressBarBuilder pbb = new ProgressBarBuilder().setTaskName(task); return wrap(writer, pbb); } /** * Wraps a {@link Writer} so that when written, a progress bar is shown to track the writing progress. * For this function the progress bar can be fully customized by using a {@link ProgressBarBuilder}. * @param writer Writer to be wrapped * @param pbb An instance of a {@link ProgressBarBuilder} */ public static Writer wrap(Writer writer, ProgressBarBuilder pbb) { return new ProgressBarWrappedWriter(writer, pbb.build()); } /** * Wraps a {@link Spliterator} so that when iterated, a progress bar is shown to track the traversal progress. * @param sp Underlying spliterator * @param task Task name */ public static Spliterator wrap(Spliterator sp, String task) { ProgressBarBuilder pbb = new ProgressBarBuilder().setTaskName(task); return wrap(sp, pbb); } /** * Wraps a {@link Spliterator} so that when iterated, a progress bar is shown to track the traversal progress. * For this function the progress bar can be fully customized by using a {@link ProgressBarBuilder}. * @param sp Underlying spliterator * @param pbb An instance of a {@link ProgressBarBuilder} */ public static Spliterator wrap(Spliterator sp, ProgressBarBuilder pbb) { if (!pbb.initialMaxIsSet()) pbb.setInitialMax(Util.getSpliteratorSize(sp)); return new ProgressBarWrappedSpliterator<>(sp, pbb.build()); } /** * Wraps a {@link Stream} so that when iterated, a progress bar is shown to track the traversal progress. * @param stream Underlying stream (can be sequential or parallel) * @param task Task name */ public static > Stream wrap(S stream, String task) { ProgressBarBuilder pbb = new ProgressBarBuilder().setTaskName(task); return wrap(stream, pbb); } /** * Wraps a {@link Stream} so that when iterated, a progress bar is shown to track the traversal progress. * For this function the progress bar can be fully customized by using a {@link ProgressBarBuilder}. * @param stream Underlying stream (can be sequential or parallel) * @param pbb An instance of a {@link ProgressBarBuilder} */ public static > Stream wrap(S stream, ProgressBarBuilder pbb) { Spliterator sp = wrap(stream.spliterator(), pbb); return StreamSupport.stream(sp, stream.isParallel()); } /** * Wraps an array so that when iterated, a progress bar is shown to track the traversal progress. * @param array Array to be wrapped * @param task Task name * @return Wrapped array, of type {@link Stream}. */ public static Stream wrap(T[] array, String task) { ProgressBarBuilder pbb = new ProgressBarBuilder().setTaskName(task); return wrap(array, pbb); } /** * Wraps an array so that when iterated, a progress bar is shown to track the traversal progress. * For this function the progress bar can be fully customized by using a {@link ProgressBarBuilder}. * @param array Array to be wrapped * @param pbb An instance of a {@link ProgressBarBuilder} * @return Wrapped array, of type {@link Stream}. */ public static Stream wrap(T[] array, ProgressBarBuilder pbb) { pbb.setInitialMax(array.length); return wrap(Arrays.stream(array), pbb); } /** Creates a new builder to customize a progress bar. */ public static ProgressBarBuilder builder() { return new ProgressBarBuilder(); } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy