แถบความคืบหน้าบรรทัดคำสั่งใน Java


130

ฉันมีโปรแกรม Java ที่ทำงานในโหมดบรรทัดคำสั่ง ฉันต้องการแสดงแถบความคืบหน้าเพื่อแสดงเปอร์เซ็นต์ของงานที่ทำ แถบความคืบหน้าแบบเดียวกับที่คุณจะเห็นโดยใช้ wget ภายใต้ unix เป็นไปได้หรือไม่


ฉันไม่รู้คำตอบสำหรับคำถามเฉพาะของคุณ แต่คุณสามารถเริ่มต้นด้วยการตรวจสอบไลบรารีที่กล่าวถึงในคำถามนี้: stackoverflow.com/questions/435740/…
Jonik

ขอบคุณ ไลบรารีที่อ้างถึงมีข้อมูลเพิ่มเติมเกี่ยวกับการแยกวิเคราะห์อาร์กิวเมนต์บรรทัดคำสั่งแทนที่จะแสดงในคอนโซล แต่ขอบคุณอย่างไรก็ตาม
g andrieu

7
นี่คือหัวข้อ OP ถามว่าเป็นไปได้หรือไม่สำหรับคำแนะนำห้องสมุด (อย่างน้อยในการแก้ไขปัจจุบัน)
Neil McGuigan

ฉันลองใช้รหัสนี้stackoverflow.com/questions/1001290/…แล้วรัน! (แก้ไขการทำงานในเทอร์มินัลเท่านั้นห้ามใช้ใน Eclipse)
Wendel

คำตอบ:


177

ฉันเคยใช้สิ่งนี้มาก่อน มันไม่ได้เกี่ยวกับ java มากนัก แต่จะส่งอักขระใดไปยังคอนโซล

ที่สำคัญคือความแตกต่างระหว่างและ \n ไปที่จุดเริ่มต้นของบรรทัดใหม่ แต่เป็นเพียงการกลับรถ - กลับไปที่จุดเริ่มต้นของบรรทัดเดียวกัน\r\n\r

สิ่งที่ต้องทำคือพิมพ์แถบความคืบหน้าของคุณตัวอย่างเช่นโดยการพิมพ์สตริง

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

ในขีดถัดไปของแถบความคืบหน้าให้เขียนทับบรรทัดเดียวกันด้วยแถบที่ยาวขึ้น (เนื่องจากเราใช้ \ r เราจึงอยู่ในบรรทัดเดียวกัน) ตัวอย่างเช่น:

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

สิ่งที่คุณต้องจำไว้ว่าทำคือเมื่อเสร็จแล้วถ้าคุณเพียงแค่พิมพ์

"done!\n"

คุณอาจยังมีขยะจากแถบความคืบหน้าในบรรทัด ดังนั้นหลังจากที่คุณใช้แถบความคืบหน้าเสร็จแล้วอย่าลืมพิมพ์ช่องว่างให้เพียงพอที่จะลบออกจากบรรทัด เช่น:

"done             |\n"

หวังว่าจะช่วยได้


นี่คือการข้ามแพลตฟอร์มจริงหรือ? มันอาจจะทำงานได้ดีบน Windows และ Linux แต่ Macs ล่ะ? ฉันไม่มีก็เลยลองไม่ได้ ...
Radu Murzea

2
@RaduMurzea OS X เป็น * NIX OS ดังนั้นหากใช้งานได้บน Linux มันจะทำงานบน OS X (นั่นไม่จริงสำหรับทุกอย่าง แต่เป็นเรื่องจริงที่นี่)
bfontaine

3
ขอบคุณ! อย่างไรก็ตามสิ่งนี้ใช้ไม่ได้กับ ant (ลองทั้งบน linux และ osx ทำงานได้ดีเมื่อเรียกใช้ java โดยตรง) ใครมีความคิด?
user495285

โปรดทราบว่าสิ่งนี้ใช้ไม่ได้ใน eclipse ที่สร้างขึ้นในคอนโซล (อย่างน้อยสำหรับฉัน) แต่เนื่องจากนี่เป็นคอนโซลการพัฒนาจึงไม่ควรมีความสำคัญมากเกินไป
Qw3ry

ฉันพบสิ่งนี้: stackoverflow.com/questions/1001290/…
Wendel

46

มีhttps://github.com/ctongfei/progressbarใบอนุญาต: MIT

แถบความคืบหน้าคอนโซลที่เรียบง่าย ขณะนี้การเขียนแถบความคืบหน้าทำงานบนเธรดอื่น

แนะนำให้ใช้ Menlo, Fira Mono, Source Code Pro หรือ SF Mono สำหรับเอฟเฟกต์ภาพที่ดีที่สุด

สำหรับฟอนต์ Consolas หรือ Andale Mono ให้ใช้ProgressBarStyle.ASCII(ดูด้านล่าง) เนื่องจากร่ายมนตร์วาดกล่องไม่ได้จัดแนวอย่างถูกต้องในฟอนต์เหล่านี้

Maven:

<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()เมธอดจะแทนที่เหตุการณ์ที่เกิดขึ้น\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 (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.printใน Java อย่าลังเลที่จะแก้ไขฉันถ้าฉันผิด

โดยทั่วไปคุณต้องการเขียน\rอักขระ Escape ที่จุดเริ่มต้นของข้อความของคุณซึ่งจะทำให้เคอร์เซอร์กลับไปที่จุดเริ่มต้นของบรรทัด (Line Feed) โดยไม่ต้องย้ายไปที่บรรทัดถัดไป

    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.