Java 中的命令行进度条

我有一个 Java 程序在命令行模式下运行。 我想显示一个进度条,显示完成工作的百分比。 与在 unix 下使用 wget 时看到的进度条类似。 这可能吗?

115706 次浏览

使用 JavaCurses 库可以做到这一点。这个是我找到的。我自己还没用过,也不知道是不是跨平台的。

C # 示例,但我假设 Java 中的 System.out.print也是如此。 如果我说错了,你可以纠正我。

基本上,您希望在消息的开头写出 \r转义字符 这将导致光标返回到行的开始(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();


}

我以前也实施过这种东西。这与 java 没有太大关系,而是要将哪些字符发送到控制台。

关键是 \n\r的区别。 \n开始一条新的生产线。但是 \r只是 回程马车-它回到同一行的开始。

所以要做的就是打印进度条,例如,打印字符串

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

在进度条的下一个刻度上,用较长的条覆盖同一行。(因为我们使用 r,所以我们保持在同一行上)例如:

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

你必须记住的是,当你完成了,如果你只是打印

"done!\n"

您可能还有一些来自进度条的垃圾在线上。因此,在您完成进度条之后,一定要打印足够的空格来从行中删除它。例如:

"done             |\n"

希望能帮上忙。

我发现下面的代码可以正常工作。它将字节写入输出缓冲区。也许使用像 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);
}
}
}

当我需要延迟一个工具以防止竞态条件时,我使用一个“弹跳”进度条。

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

以下是上述内容的修改版本:

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

我已经取得了一个百分比的进展裸检查剩余的下载文件。

我在文件下载中定期调用该方法来检查文件总大小和剩余大小,并在 %中显示。

它也可以用于其他任务目的。

测试和输出示例

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


}


}

有点重构和更新@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");
}
}
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()) + "]";
}

image

我编辑了 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

没必要搞得这么复杂。

enter image description here

public class Demo {
private static final StringBuilder sb = new StringBuilder();


public static void main (String[] args) throws java.lang.Exception
{
for (int i = 0 ; i <= 100 ; i++) {
sb.setLength(0);
for (int j = 0 ; j < i; j++) {
sb.append("#");
}
Thread.sleep(100);
System.out.print("[" + String.format("%-100s", sb.toString()) + "] " +  i + "%");
System.out.print("\r");
}
}
}


public class ConsoleApp {
static String DisplayBar(int i)
{
StringBuilder sb = new StringBuilder();


int x = i / 2;
sb.append("|");
for (int k = 0; k < 50; k++)
sb.append(String.format("%s", ((x <= k) ? " " : "=")));
sb.append("|");


return sb.toString();
}


public static void main(String[] args) throws InterruptedException {
for (int i = 0; i <= 100; i++)
{
Thread.sleep(200);
System.out.printf("\r%s %s  Done", DisplayBar(i), i);
}
}
}

我已经创建了一个 进度条,其中包含你可能需要的一切。

我甚至 记录在案它!

我也编辑了更快的使用。

我知道没有人必须这样做,但我仍然看到人们有同样的问题10年后!

这里有一个例子:

//...
//For demo only!
public static void main(String[]a){
final ProgressBar progress=new ProgressBar(100);
progress.printBar();
for(int i=0;i<100;i++){
progress.addValue();
progress.printBar();
try{
java.lang.Thread.sleep(100);
}catch(Exception e){}
}
}
//...

这不是为了促销,做了这个是为了帮助人们不要把时间浪费在自己编码类上!