用于多个文件下载的java progressbar

时间:2015-12-02 23:44:33

标签: java swing timer progress-bar

我必须为项目制作一个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取决于文件。如何获取整体下载的内容? 提前谢谢

1 个答案:

答案 0 :(得分:2)

从概念上讲,您有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,它被传递给SwingWorker,以允许它向另一方提供有关进度状态更改的通知。然后,用户界面会在Map中维护有关每个工作人员进度的信息,该信息用于计算sum以及由此产生的总进度。基本上是相同的概念,只是在一个更动态的例子中

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

    }

}

出于示例的目的,每个worker都提供了一个int索引,这可用于提供一些额外的调试,以便您可以看到每个更新的方式