gpt4 book ai didi

java用于多个文件下载的进度条

转载 作者:行者123 更新时间:2023-12-02 04:08:08 25 4
gpt4 key购买 nike

我必须为一个项目制作一个小p2p 程序。一切正常。我已经设置客户端可以一次下载多个文件(下载使用线程)。我现在的问题是如何才能真正获得下载的总体进度。我尝试了这样的方法,但没有成功

try {
int bytesRead;
InputStream in = mySocket.getInputStream();
DataInputStream clientData = new DataInputStream(in);
OutputStream output = new FileOutputStream(("./download/" + filename));
byte[] buffer = new byte[1024];
int currentProgress = 0;
while (filesize > 0 && (bytesRead = clientData.read(buffer, 0, (int) Math.min(buffer.length, filesize))) != -1) {
output.write(buffer, 0, bytesRead);
filesize -= bytesRead;
currentProgress = (int) ((((double)filesize) / ((double)size)) * 100d);
currentProgress = ((100-currentProgress)/ViewClient.countFiles);
System.out.println(currentProgress);
}
output.close();
in.close();
System.out.println("File "+filename+" received from client.");
} catch (IOException ex) {
ex.printStackTrace();
}

这样,每个值(0,1,2,3)将被打印 100 次,然后我的进度条有时会达到 2'000'000,具体取决于文件。如何获取全部下载内容?预先感谢您

最佳答案

从概念上讲,您有 n 个任务,每个任务都会生成 0-100% 之间的进度。

为了简单起见,我将使用 0-1 作为进度值。

您获取每个任务的进度并将其相加,然后除以任务数量,这将为您提供 0-1 之间的总体进度,例如...

int taskCount = 10;
List<Double> taskProgress = new ArrayList<>(taskCount);
for (int index = 0; index < taskCount; index++) {
taskProgress.add(0.0);
}

double overallProgress = 0;
int round = 0;
do {
round++;
double sum = 0;
for (int index = 0; index < taskCount; index++) {
double progress = taskProgress.get(index);
progress += Math.random() * 0.1;
progress = Math.min(progress, 1.0);
sum += progress;
taskProgress.set(index, progress);
}
overallProgress = sum / (double)taskCount;
System.out.println("[" + round + "] " + NumberFormat.getPercentInstance().format(overallProgress) + "; " + NumberFormat.getNumberInstance().format(overallProgress));
} while (overallProgress < 1.0);

可以打印...

[1] 5%; 0.049
[2] 9%; 0.09
[3] 14%; 0.144
[4] 18%; 0.179
[5] 23%; 0.23
[6] 28%; 0.276
[7] 32%; 0.321
[8] 37%; 0.366
[9] 40%; 0.403
[10] 45%; 0.451
[11] 51%; 0.505
[12] 55%; 0.552
[13] 60%; 0.601
[14] 64%; 0.642
[15] 69%; 0.695
[16] 76%; 0.761
[17] 80%; 0.803
[18] 84%; 0.845
[19] 87%; 0.869
[20] 90%; 0.902
[21] 92%; 0.925
[22] 95%; 0.946
[23] 96%; 0.962
[24] 97%; 0.971
[25] 98%; 0.976
[26] 99%; 0.986
[27] 99%; 0.989
[28] 99%; 0.993
[29] 100%; 1

使用基于 Swing 的示例进行了更新

因此,这基本上使用 SwingWorker 来执行后台任务,这基本上将进度值增加随机量(然后暂停随机时间量)。工作线程通过其 publish/process 方法提供进度更改通知,该方法向感兴趣的各方提供返回通知,但在事件调度线程的上下文中执行此操作。

该示例使用了一个简单的接口(interface),该接口(interface)被传递给SwingWorker,以允许它向另一方提供有关进度状态更改的通知。然后,UI 在Map 中维护有关每个工作人员进度的信息,该信息用于计算总和 以及由此产生的总进度。本质上与上面的概念相同,只是在一个更动态的示例中

Progress

import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingWorker;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class ProgressTest {

public static void main(String[] args) {
new ProgressTest();
}

public ProgressTest() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}

JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}

public class TestPane extends JPanel implements ProgressMonitor{

private Map<DownloadWorker, Double> workerProgress;
private int taskCount;
private double progress;

public TestPane() {
workerProgress = new HashMap<>(25);
taskCount = 10;
for (int index = 0; index < 10; index++) {
DownloadWorker worker = new DownloadWorker(index, this);
workerProgress.put(worker, 0d);
worker.execute();
}
}

@Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}

@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
int width = (int)Math.round(getWidth() * progress);
g2d.setColor(UIManager.getColor("ProgressBar.selectionBackground"));
g2d.fillRect(0, 0, width, getHeight());
g2d.dispose();
}

@Override
public void progressWasUpdated(DownloadWorker worker, double progress) {
workerProgress.put(worker, progress);
double sum = 0;
for (Map.Entry<DownloadWorker, Double> entry : workerProgress.entrySet()) {
sum += entry.getValue();
}
this.progress = sum / (double)taskCount;
repaint();
}

}

public interface ProgressMonitor {
public void progressWasUpdated(DownloadWorker worker, double progress);
}

private Random rnd = new Random();

public class DownloadWorker extends SwingWorker<Void, Double> {

private int index;
private ProgressMonitor progressMonitor;

public DownloadWorker(int index, ProgressMonitor progressMonitor) {
this.progressMonitor = progressMonitor;
this.index = index;
}

@Override
protected Void doInBackground() throws Exception {
double progress = 0;
do {
progress += Math.random() * 0.1;
progress = Math.min(progress, 1.0);
publish(progress);
Thread.sleep(rnd.nextInt(490) + 10);
} while (progress < 1.0);
publish(1.0);
System.out.println(index + " has ended");
return null;
}

public int getIndex() {
return index;
}

@Override
protected void process(List<Double> chunks) {
progressMonitor.progressWasUpdated(this, chunks.get(chunks.size() - 1));
}

}

}

出于示例的目的,每个工作线程都提供了一个 int 索引,这可用于提供一些额外的调试,以便您可以查看每个工作线程是如何更新的

关于java用于多个文件下载的进度条,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34055285/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com