Mam program Java działający w trybie wiersza poleceń. Chciałbym wyświetlić pasek postępu, pokazujący procent wykonanej pracy. Ten sam rodzaj paska postępu, jaki zobaczysz używając wget pod unixem. czy to możliwe?
Mam program Java działający w trybie wiersza poleceń. Chciałbym wyświetlić pasek postępu, pokazujący procent wykonanej pracy. Ten sam rodzaj paska postępu, jaki zobaczysz używając wget pod unixem. czy to możliwe?
Odpowiedzi:
Wdrożyłem już tego typu rzeczy. Nie chodzi tu o Javę, ale o to, jakie znaki wysłać na konsolę.
Kluczem jest różnica między \n
i \r
.
\n
przechodzi na początek nowej linii. Ale \r
to tylko powrót karetki - wraca do początku tej samej linii.
Więc chodzi o wydrukowanie paska postępu, na przykład przez wydrukowanie ciągu
"|======== |\r"
Przy następnym znaczniku paska postępu nadpisz tę samą linię dłuższym paskiem. (ponieważ używamy \ r, pozostajemy w tej samej linii) Na przykład:
"|========= |\r"
To, o czym musisz pamiętać, jest po zakończeniu, jeśli po prostu drukujesz
"done!\n"
Nadal możesz mieć trochę śmieci z paska postępu w linii. Więc kiedy skończysz z paskiem postępu, upewnij się, że wypisałeś wystarczającą ilość spacji, aby usunąć go z wiersza. Jak na przykład:
"done |\n"
Mam nadzieję, że to pomoże.
Jest https://github.com/ctongfei/progressbar , Licencja: MIT
Prosty pasek postępu konsoli. Pisanie na pasku postępu działa teraz w innym wątku.
W celu uzyskania optymalnych efektów wizualnych zalecane są Menlo, Fira Mono, Source Code Pro lub SF Mono.
W przypadku czcionek Consolas lub Andale Mono użyj ProgressBarStyle.ASCII
(patrz poniżej), ponieważ glify do rysowania pudełek nie są prawidłowo wyrównane w tych czcionkach.
Maven:
<dependency>
<groupId>me.tongfei</groupId>
<artifactId>progressbar</artifactId>
<version>0.5.5</version>
</dependency>
Stosowanie:
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
step()
połączeniami)? Czy Twoja biblioteka działa asynchronicznie, co pozwala na aktualizację zegara? A jeśli moja biblioteka będzie działać przez kilka dni? Czy używa /r
strategii? Czy spowoduje to wieluset megabajtową produkcję?
Uważam, że następujący kod działa poprawnie. Zapisuje bajty do bufora wyjściowego. Być może te metody wykorzystujące moduł zapisujący, taki jak System.out.println()
metoda, zastępują wystąpienia \r
do, \n
aby dopasować natywne zakończenie wiersza celu (jeśli nie jest poprawnie skonfigurowane).
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);
}
}
}
Zrobiłem procentowy postęp, aby sprawdzić pozostały plik do pobrania.
Wywołuję tę metodę okresowo w moim pobieraniu pliku, aby sprawdzić całkowity rozmiar pliku i pozostały rozmiar i przedstawić go w %
.
Może być również używany do innych celów.
Przykład testu i wyjścia
progressPercentage(0, 1000);
[----------] 0%
progressPercentage(10, 100);
[*---------] 10%
progressPercentage(500000, 1000000);
[*****-----] 50%
progressPercentage(90, 100);
[*********-] 90%
progressPercentage(1000, 1000);
[**********] 100%
Przetestuj za pomocą pętli for
for (int i = 0; i <= 200; i = i + 20) {
progressPercentage(i, 200);
try {
Thread.sleep(500);
} catch (Exception e) {
}
}
Metodę można łatwo zmodyfikować:
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");
}
}
Przykład C #, ale zakładam, że jest to to samo System.out.print
w Javie. Możesz mnie poprawić, jeśli się mylę.
Zasadniczo chcesz wypisać \r
znak ucieczki na początku wiadomości, co spowoduje, że kursor wróci na początek wiersza (przesunięcie o wiersz) bez przechodzenia do następnego wiersza.
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();
}
Trochę refaktoryzowana i zaktualizowana metoda @ maytham-ɯɐɥʇʎɐɯ. Teraz obsługuje dowolny rozmiar paska postępu:
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");
}
}
Oto zmodyfikowana wersja powyższego:
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();
}
... a przede wszystkim:
loading("Calculating ...");
Używam „odbijającego się” paska postępu, gdy muszę opóźnić narzędzie, aby zapobiec sytuacji wyścigu.
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");
}
Niedawno spotkałem się z tym samym problemem, możesz sprawdzić mój kod: ustawiłem go na jeden # na 5%, który możesz później zmodyfikować.
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();
}
Edytowałem kod Eoina Campbella w Javie i dodałem sformatowany postęp w procentach.
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");
I wyjście:
Generating report...
[======== 24.2 % ]
[============ 45.5 % ]
[============ 78.8 % ===== ]
[============ 87.9 % ======== ]
[============ 100.0 % ============]
Successfully saved 32128 bytes
String formattedPercent = String.format(" %5.1f %% ", (100 * currentProgressBarIndex) / (double) progressBarLength);
zString formattedPercent = String.format(" %7.3f %% ", (100 * currentValue) / (double) maxValue);
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();
}
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);
}
}
}
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()) + "]";
}