[java] Java의 명령 행 진행률 표시 줄

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



답변

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

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

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

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

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

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

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

"done!\n"

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

"done             |\n"

희망이 도움이됩니다.


답변

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


답변

다음 코드가 올바르게 작동한다는 것을 알았습니다. 출력 버퍼에 바이트를 씁니다. 아마도 메소드와 같은 라이터를 사용하는 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);
        }
    }
}


답변

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

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

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

테스트 및 출력 예

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");
    }
}


답변

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();

    }


답변

@ 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");
        }
    }


답변

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

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 ...");