准确汇总文件大小以在 JProgressBar 中使用

Posted

技术标签:

【中文标题】准确汇总文件大小以在 JProgressBar 中使用【英文标题】:Accurately summing file sizes to use in a JProgressBar 【发布时间】:2014-10-30 13:47:14 【问题描述】:

我有一个要复制到另一个位置的文件列表,我想使用 JProgressBar 来监控传输进度。

JProgressBar 构造函数只接受一个 int 作为边界,而 File.length 返回一个 long。我知道我可以将 long 转换为 int 并失去一些准确性,但这是正确的方法吗?

我没有包含任何代码,因为这实际上不是语法或编码问题,我只是不确定将 long 转换为 int 以用于进度条对于我的目的是否正确或准确。

【问题讨论】:

double bytes = file.length(); double kilobytes = (bytes / 1024); double megabytes = (kilobytes / 1024); double gigabytes = (megabytes / 1024); double terabytes = (gigabytes / 1024);你可以将大小转换成字节然后尝试求和 除非您的 long 超出最大 int 的大小,否则您不会失去任何准确性,这在这种情况下是值得怀疑的。 @HovercraftFullOfEels 我什至没有想到这一点。谢谢 一个 int 最多只能存储 4Gb - 这些天几乎没有很多数据。 @BarrySW19 你是说只要我的文件小于 4Gb 我就可以了吗? 【参考方案1】:

我并没有真正看到关于进度条边界的问题,因为实际进度是从 0 到 100 的百分比值。您应该始终能够计算已处理字节数与总字节数之间的比例,这就是实际的进展。

我认为正确的问题应该是:如何根据文件长度和要传输的总字节数正确更新进度条的进度?

考虑这个例子:

import java.awt.event.ActionEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.File;
import java.util.List;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.SwingUtilities;
import javax.swing.SwingWorker;

public class Demo 

    private void createAndShowGUI() 

        final JProgressBar progressBar = new JProgressBar();
        progressBar.setStringPainted(true);
        progressBar.setString("");

        final SwingWorker<Void,String> worker = new SwingWorker<Void, String>() 
            @Override
            protected Void doInBackground() throws Exception 

                long totalSize = 0l;

                File[] files = new File(System.getProperty("user.dir")).listFiles();
                for (File file : files) 
                    totalSize += file.length();
                

                long transferred = 0l;

                for (File file : files)                     
                    Thread.sleep(250); // Just for animation purpose
                    transferred += file.length();
                    int progress = (int) (transferred * 100l / totalSize);
                    setProgress(progress);

                    String text = String.format("%1s%%: %2s / %3s bytes", progress, transferred, totalSize);
                    publish(text);
                

                return null;
            

            @Override
            protected void process(List<String> chunks) 
                progressBar.setString(chunks.get(chunks.size() - 1));
            
        ;

        worker.addPropertyChangeListener(new PropertyChangeListener() 
            @Override
            public void propertyChange(PropertyChangeEvent evt) 
                if ("progress".equals(evt.getPropertyName())) 
                    progressBar.setValue((Integer)evt.getNewValue());
                
            
        );

        Action startAction = new AbstractAction("Start") 
            @Override
            public void actionPerformed(ActionEvent e) 
                worker.execute();
                setEnabled(false);
            
        ;

        JPanel content = new JPanel();
        content.add(progressBar);
        content.add(new JButton(startAction));

        JFrame frame = new JFrame("Demo");
        frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
        frame.add(content);
        frame.pack();
        frame.setLocationByPlatform(true);
        frame.setVisible(true);

    

    public static void main(String[] args) 
        SwingUtilities.invokeLater(new Runnable() 
            @Override
            public void run() 
                new Demo().createAndShowGUI();
            
        );
        

因为transferred * 100l / totalSize 始终是介于 0 和 100 之间的值,所以您可能会丢失小数点精度,但绝对不会丢失将其精确转换为 int 以设置进度条值。

【讨论】:

以上是关于准确汇总文件大小以在 JProgressBar 中使用的主要内容,如果未能解决你的问题,请参考以下文章

更改缓冲区大小以在 C 中复制文件

JTable的TableColumn添加多个JProgressBar

如何将JProgressbar绑定到Bean类的属性

如何在 jprogressbar 上添加文本?

Java Swing 之Timer配合JProgressBar的使用

JProgressBar setValue 不起作用,也尝试使用 SwingUtilities