Java의 명령 행 진행률 표시 줄


130

커맨드 라인 모드에서 실행중인 Java 프로그램이 있습니다. 진행률 표시 줄을 표시하여 작업 비율을 표시하고 싶습니다. 유닉스에서 wget을 사용하는 것과 같은 진행률 표시 줄. 이게 가능해?


구체적인 질문에 대한 답을 모르지만이 질문에 언급 된 라이브러리를 확인하여 시작할 수 있습니다. stackoverflow.com/questions/435740/…
Jonik

감사. 라이브러리는 콘솔에 표시하는 대신 명령 행 인수 구문 분석에 대해 더 많이 언급했습니다. 그러나 어쨌든 감사합니다.
g andrieu

7
이것은 주제입니다. 가능하면 영업 이익은 (적어도 현재 편집에서)하지 도서관 추천에 대한 요청
닐 맥기에게

나는이 코드를 시도 stackoverflow.com/questions/1001290/... 실행을! (터미널에서만 올바르게 실행, Eclipse에서는 사용하지 마십시오)
Wendel

답변:


176

나는 전에 이런 종류의 것을 구현했습니다. 그것은 자바에 관한 것이 아니라 콘솔에 보낼 문자입니다.

열쇠 간의 차이 \n\r. \n새로운 줄의 시작으로갑니다. 그러나 캐리지 리턴\r 일뿐 입니다. 같은 라인의 시작 부분으로 돌아갑니다.

따라서해야 할 일은 예를 들어 문자열을 인쇄하여 진행률 표시 줄을 인쇄하는 것입니다.

"|========        |\r"

진행률 표시 줄의 다음 눈금에서 동일한 줄을 더 긴 막대로 덮어 씁니다. (\ r을 사용하고 있기 때문에 같은 줄을 유지합니다) 예를 들면 다음과 같습니다.

"|=========       |\r"

기억해야 할 것은 완료되면 인쇄 한 다음 인쇄하는 것입니다.

"done!\n"

회선의 진행률 표시 줄에 쓰레기가 남아있을 수 있습니다. 따라서 진행률 표시 줄을 다 사용한 후에는 공백을 인쇄하여 줄에서 제거하십시오. 같은 :

"done             |\n"

희망이 도움이됩니다.


이것이 실제로 크로스 플랫폼입니까? 아마도 Windows와 Linux에서는 정상적으로 작동하지만 Mac은 어떻습니까? 나는 하나도 없어서 시도해 볼 수 없다 ...
Radu Murzea

2
@RaduMurzea OS X는 * NIX OS이므로 Linux에서 작동하면 OS X에서 작동합니다 (모든 경우에 해당되는 것은 아니지만 여기서는 사실임).
bfontaine

3
감사! 그러나 이것은 ant와는 작동하지 않습니다 (linux와 osx에서 모두 시도했습니다 .java를 직접 호출 할 때 잘 작동합니다). 어떤 아이디어가 있습니까?
user495285

이것은 콘솔에 내장 된 일식에서는 작동하지 않습니다 (적어도 나를 위해). 그러나 이것은 개발 콘솔이므로 너무 중요하지 않아야합니다.
Qw3ry


46

https://github.com/ctongfei/progressbar 라이센스 : MIT

간단한 콘솔 진행 표시 줄. 진행률 표시 줄 쓰기가 이제 다른 스레드에서 실행됩니다.

최적의 시각 효과를 위해서는 Menlo, Fira Mono, Source Code Pro 또는 SF Mono가 권장됩니다.

Consolas 또는 Andale Mono 글꼴의 ProgressBarStyle.ASCII경우 상자 글꼴 글리프가 이러한 글꼴에서 올바르게 정렬되지 않으므로 (아래 참조)를 사용 하십시오.

메이븐 :

<dependency>
  <groupId>me.tongfei</groupId>
  <artifactId>progressbar</artifactId>
  <version>0.5.5</version>
</dependency>

용법:

ProgressBar pb = new ProgressBar("Test", 100); // name, initial max
 // Use ProgressBar("Test", 100, ProgressBarStyle.ASCII) if you want ASCII output style
pb.start(); // the progress bar starts timing
// Or you could combine these two lines like this:
//   ProgressBar pb = new ProgressBar("Test", 100).start();
some loop {
  ...
  pb.step(); // step by 1
  pb.stepBy(n); // step by n
  ...
  pb.stepTo(n); // step directly to n
  ...
  pb.maxHint(n);
  // reset the max of this progress bar as n. This may be useful when the program
  // gets new information about the current progress.
  // Can set n to be less than zero: this means that this progress bar would become
  // indefinite: the max would be unknown.
  ...
  pb.setExtraMessage("Reading..."); // Set extra message to display at the end of the bar
}
pb.stop() // stops the progress bar

1
이것은 깔끔해 보이며 CLI에있는 수백 개의 문자열 버퍼 라인을 대체 할 수 있습니다. 그러나 "틱"(분) 사이에 몇 분 동안 실행되는 응용 프로그램이 있으면 어떻게 step()됩니까? 라이브러리가 비동기식으로 실행되어 시계가 업데이트됩니까? 내 도서관이 며칠 동안 운영되면 어떻게 되나요? /r전략을 사용합니까 ? 그 결과 수백 메가 바이트 출력이 발생합니까?
Groostav

23

다음 코드가 올바르게 작동한다는 것을 알았습니다. 출력 버퍼에 바이트를 씁니다. 아마도 메소드와 같은 라이터를 사용하는 System.out.println()메소드는 대상의 기본 줄 끝 (올바로 구성되지 않은 경우)과 일치하도록 of \r를 대체합니다 \n.

public class Main{
    public static void main(String[] arg) throws Exception {
        String anim= "|/-\\";
        for (int x =0 ; x < 100 ; x++) {
            String data = "\r" + anim.charAt(x % anim.length()) + " " + x;
            System.out.write(data.getBytes());
            Thread.sleep(100);
        }
    }
}

7

남아있는 다운로드 파일을 확인하기 위해 백분율 진행을 진행했습니다.

파일 다운로드에서 메소드를 주기적으로 호출하여 총 파일 크기를 확인하고 나머지 파일을에 표시 %합니다.

다른 작업 목적으로도 사용할 수 있습니다.

테스트 및 출력 예

progressPercentage(0, 1000);
[----------] 0%

progressPercentage(10, 100);
[*---------] 10%

progressPercentage(500000, 1000000);
[*****-----] 50%

progressPercentage(90, 100);
[*********-] 90%

progressPercentage(1000, 1000);
[**********] 100%

for 루프로 테스트

for (int i = 0; i <= 200; i = i + 20) {
    progressPercentage(i, 200);
    try {
        Thread.sleep(500);
    } catch (Exception e) {
    }
}

이 방법은 쉽게 수정할 수 있습니다.

public static void progressPercentage(int remain, int total) {
    if (remain > total) {
        throw new IllegalArgumentException();
    }
    int maxBareSize = 10; // 10unit for 100%
    int remainProcent = ((100 * remain) / total) / maxBareSize;
    char defaultChar = '-';
    String icon = "*";
    String bare = new String(new char[maxBareSize]).replace('\0', defaultChar) + "]";
    StringBuilder bareDone = new StringBuilder();
    bareDone.append("[");
    for (int i = 0; i < remainProcent; i++) {
        bareDone.append(icon);
    }
    String bareRemain = bare.substring(remainProcent, bare.length());
    System.out.print("\r" + bareDone + bareRemain + " " + remainProcent * 10 + "%");
    if (remain == total) {
        System.out.print("\n");
    }
}

5

C # 예제이지만 System.out.printJava 에서도 동일하다고 가정합니다 . 내가 틀렸다면 자유롭게 고쳐주세요.

기본적으로 \r메시지의 시작 부분에 이스케이프 문자 를 쓰면 커서가 다음 줄로 이동하지 않고 줄의 시작 (줄 바꿈)으로 돌아갑니다.

    static string DisplayBar(int i)
    {
        StringBuilder sb = new StringBuilder();

        int x = i / 2;
        sb.Append("|");
        for (int k = 0; k < 50; k++)
            sb.AppendFormat("{0}", ((x <= k) ? " " : "="));
        sb.Append("|");

        return sb.ToString();
    }

    static void Main(string[] args)
    {
        for (int i = 0; i <= 100; i++)
        {
            System.Threading.Thread.Sleep(200);
            Console.Write("\r{0} {1}% Done", DisplayBar(i), i);
        }

        Console.ReadLine();

    }

좋은 예, 확실히 도움이 될 것입니다. 감사.
g andrieu

아름다운! 감사합니다. 매력처럼 작동합니다. 읽기 쉬운. 사랑스러운
kholofelo Maloma

4

@ maytham-ɯɐɥʇʎɐɯ의 방법을 약간 리팩토링하고 업데이트했습니다. 이제 진행률 표시 줄의 임의 크기를 지원합니다.

    public static void progressPercentage(int done, int total) {
        int size = 5;
        String iconLeftBoundary = "[";
        String iconDone = "=";
        String iconRemain = ".";
        String iconRightBoundary = "]";

        if (done > total) {
            throw new IllegalArgumentException();
        }
        int donePercents = (100 * done) / total;
        int doneLength = size * donePercents / 100;

        StringBuilder bar = new StringBuilder(iconLeftBoundary);
        for (int i = 0; i < size; i++) {
            if (i < doneLength) {
                bar.append(iconDone);
            } else {
                bar.append(iconRemain);
            }
        }
        bar.append(iconRightBoundary);

        System.out.print("\r" + bar + " " + donePercents + "%");

        if (done == total) {
            System.out.print("\n");
        }
    }

3

위의 수정 된 버전은 다음과 같습니다.

private static boolean loading = true;
private static synchronized void loading(String msg) throws IOException, InterruptedException {
    System.out.println(msg);
    Thread th = new Thread() {
        @Override
        public void run() {
            try {
                System.out.write("\r|".getBytes());
                while(loading) {
                    System.out.write("-".getBytes());
                    Thread.sleep(500);
                }
                System.out.write("| Done \r\n".getBytes());
            } catch (IOException e) {
                e.printStackTrace();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    };
    th.start();
}

... 그리고 메인 :

loading("Calculating ...");

2

이것은 Java Curses 라이브러리에서 가능합니다. 이것이 내가 찾은 것입니다. 나는 그것을 직접 사용하지 않았고 그것이 크로스 플랫폼인지 모르겠습니다.


저주가 필요한 쉬운 사용법을 위해 약간의 오버 헤드가있을 수 있지만, 그 과정은 확실합니다. 감사.
g andrieu

2

경쟁 조건을 방지하기 위해 도구를 지연해야 할 때 "튀는"진행률 표시 줄을 사용합니다.

private void delay(long milliseconds) {
    String bar = "[--------------------]";
    String icon = "%";

    long startTime = new Date().getTime();
    boolean bouncePositive = true;
    int barPosition = 0;

    while((new Date().getTime() - startTime) < milliseconds) {
        if(barPosition < bar.length() && barPosition > 0) {
            String b1 = bar.substring(0, barPosition);
            String b2 = bar.substring(barPosition);
            System.out.print("\r Delaying: " + b1 + icon + b2);
            if(bouncePositive) barPosition++;
            else barPosition--;
        } if(barPosition == bar.length()) {
            barPosition--;
            bouncePositive = false;
        } if(barPosition == 0) {
            barPosition++;
            bouncePositive = true;
        }

        try { Thread.sleep(100); }
        catch (Exception e) {}
    }
    System.out.print("\n");
}

2

나는 최근에 같은 문제에 직면했다, 당신은 내 코드를 확인할 수 있습니다 : 나는 5 %에 ​​하나를 설정했습니다. 나중에 수정할 수 있습니다.

public static void main (String[] args) throws java.lang.Exception
{
    int i = 0;
    while(i < 21) {
        System.out.print("[");
        for (int j=0;j<i;j++) {
            System.out.print("#");
        }

        for (int j=0;j<20-i;j++) {
            System.out.print(" ");
        }

        System.out.print("] "+  i*5 + "%");
        if(i<20) {
            System.out.print("\r");
            Thread.sleep(300);
        }
        i++;
    }
    System.out.println();
}

1
public static void main(String[] argv) throws Exception{


    System.out.write("\r".getBytes());
    int percentage =10;
    while(percentage <= 100) {
        String temp =generateStars(percentage);
        System.out.write(temp.getBytes());
        System.out.print("\b\b\b");
        percentage = percentage+10;
        Thread.sleep(500);
    }
}

    public static String generateStars(int percentage)
    {
        int startsNum = percentage / 4;
        StringBuilder builder = new StringBuilder();
        while(startsNum >= 0)
        {
        builder.append("*");
        startsNum--;
        }
        builder.append(percentage+"%");
        return builder.toString();
    }

1

Eoin Campbell의 코드를 Java로 편집하고 형식화 된 진행률을 백분율로 추가했습니다.

public static String progressBar(int currentValue, int maxValue) {
    int progressBarLength = 33; //
    if (progressBarLength < 9 || progressBarLength % 2 == 0) {
        throw new ArithmeticException("formattedPercent.length() = 9! + even number of chars (one for each side)");
    }
    int currentProgressBarIndex = (int) Math.ceil(((double) progressBarLength / maxValue) * currentValue);
    String formattedPercent = String.format(" %5.1f %% ", (100 * currentProgressBarIndex) / (double) progressBarLength);
    int percentStartIndex = ((progressBarLength - formattedPercent.length()) / 2);

    StringBuilder sb = new StringBuilder();
    sb.append("[");
    for (int progressBarIndex = 0; progressBarIndex < progressBarLength; progressBarIndex++) {
        if (progressBarIndex <= percentStartIndex - 1
        ||  progressBarIndex >= percentStartIndex + formattedPercent.length()) {
            sb.append(currentProgressBarIndex <= progressBarIndex ? " " : "=");
        } else if (progressBarIndex == percentStartIndex) {
            sb.append(formattedPercent);
        }
    }
    sb.append("]");
    return sb.toString();
}

int max = 22;
System.out.println("Generating report...");
for (int i = 0; i <= max; i++) {
   Thread.sleep(100);
   System.out.print(String.format("\r%s", progressBar(i, max)));
}
System.out.println("\nSuccessfully saved 32128 bytes");

그리고 출력 :

Generating report...

[========      24.2 %             ]

[============  45.5 %             ]

[============  78.8 % =====       ]

[============  87.9 % ========    ]

[============ 100.0 % ============]

Successfully saved 32128 bytes

0
public class ProgressBar
{
    private int max;

    public ProgressBar(int max0) {
        max = max0;
        update(0);
    }

    public void update(int perc) {
        String toPrint = "|";
        for(int i = 0; i < max; i++) {
            if(i <= (perc + 1))
                toPrint += "=";
            else
                toPrint += " ";
        }

        if(perc >= max)
            Console.print("\r");
        else
            Console.print(toPrint + "|\r");
    }
}

0
public class Main {

    public static void main(String[] args) throws Exception {

        System.out.println("Loading : ");
            int count =1;
            for(int j=1;j<150;j++){

                System.out.print("\r");
                if(count==1){
                    System.out.print("/");
                    count++;
                }
                else if(count==2){
                    System.out.print("|");
                    count++;
                }
                else if(count==3){
                    System.out.print("-");
                    count++;
                }
                else if(count==4){
                    System.out.print("\\");
                    count++;
                }
                else if(count==5){
                    System.out.print("|");
                    count++;
                }
                else
                    count = 1;
            Thread.sleep(200);
        }

        }

    }

0
static String progressBar(int progressBarSize, long currentPosition, long startPositoin, long finishPosition) {
    String bar = "";
    int nPositions = progressBarSize;
    char pb = '░';
    char stat = '█';
    for (int p = 0; p < nPositions; p++) {
        bar += pb;
    }
    int ststus = (int) (100 * (currentPosition - startPositoin) / (finishPosition - startPositoin));
    int move = (nPositions * ststus) / 100;
    return "[" + bar.substring(0, move).replace(pb, stat) + ststus + "%" + bar.substring(move, bar.length()) + "]";
}

여기에 이미지 설명을 입력하십시오

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.