我有一个 Java 程序在命令行模式下运行。 我想显示一个进度条,显示完成工作的百分比。 与在 unix 下使用 wget 时看到的进度条类似。 这可能吗?
使用 JavaCurses 库可以做到这一点。这个是我找到的。我自己还没用过,也不知道是不是跨平台的。
C # 示例,但我假设 Java 中的 System.out.print也是如此。 如果我说错了,你可以纠正我。
System.out.print
基本上,您希望在消息的开头写出 \r转义字符 这将导致光标返回到行的开始(Line Feed)而不移动到下一行。
\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(); }
我以前也实施过这种东西。这与 java 没有太大关系,而是要将哪些字符发送到控制台。
关键是 \n和 \r的区别。 \n开始一条新的生产线。但是 \r只是 回程马车-它回到同一行的开始。
\n
所以要做的就是打印进度条,例如,打印字符串
"|======== |\r"
在进度条的下一个刻度上,用较长的条覆盖同一行。(因为我们使用 r,所以我们保持在同一行上)例如:
"|========= |\r"
你必须记住的是,当你完成了,如果你只是打印
"done!\n"
您可能还有一些来自进度条的垃圾在线上。因此,在您完成进度条之后,一定要打印足够的空格来从行中删除它。例如:
"done |\n"
希望能帮上忙。
我发现下面的代码可以正常工作。它将字节写入输出缓冲区。也许使用像 System.out.println()方法这样的编写器的方法将 \r替换为 \n,以匹配目标的本机行结尾(如果配置不当)。
System.out.println()
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(); }
有 https://github.com/ctongfei/progressbar,执照: 麻省理工学院
简单的控制台进度条。进度条写入现在在另一个线程上运行。
门洛、 Fira Mono、 Source Code Pro 或 SF Mono 是最佳视觉效果的推荐选择。
对于 Consolas 或 Andale Mono 字体,使用 ProgressBarStyle.ASCII(见下文) ,因为在这些字体中盒子绘制字形没有正确对齐。
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
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()) + "]"; }
我编辑了 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
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){} } } //...
这不是为了促销,做了这个是为了帮助人们不要把时间浪费在自己编码类上!