我有以下代码来复制目录和文件但不知道在哪里测量进度。有人可以帮忙吗 至于我在哪里可以测量复制了多少并在JProgress栏中显示它
public static void copy(File src, File dest)
throws IOException{
if(src.isDirectory()){
if(!dest.exists()){ //checking whether destination directory exisits
dest.mkdir();
System.out.println("Directory copied from "
+ src + " to " + dest);
}
String files[] = src.list();
for (String file : files) {
File srcFile = new File(src, file);
File destFile = new File(dest, file);
copyFolder(srcFile,destFile);
}
}else{
InputStream in = new FileInputStream(src);
OutputStream out = new FileOutputStream(dest);
byte[] buffer = new byte[1024];
int length;
while ((length = in.read(buffer)) > 0){
out.write(buffer, 0, length);
}
in.close();
out.close();
System.out.println("File copied from " + src + " to " + dest);
}
答案 0 :(得分:13)
我刚刚为你写了这个实用程序:)(这需要我大约3个小时):
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.List;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import javax.swing.SwingWorker;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.text.DefaultCaret;
public class FileCopierUtility extends JFrame implements ActionListener, PropertyChangeListener
{
private static final long serialVersionUID = 1L;
private JTextField txtSource;
private JTextField txtTarget;
private JProgressBar progressAll;
private JProgressBar progressCurrent;
private JTextArea txtDetails;
private JButton btnCopy;
private CopyTask task;
public FileCopierUtility()
{
buildGUI();
}
private void buildGUI()
{
setTitle("File Copier Utility");
setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);
addWindowListener(new WindowAdapter()
{
@Override
public void windowClosing(WindowEvent e)
{
if(task != null) task.cancel(true);
dispose();
System.exit(0);
}
});
JLabel lblSource = new JLabel("Source Path: ");
JLabel lblTarget = new JLabel("Target Path: ");
txtSource = new JTextField(50);
txtTarget = new JTextField(50);
JLabel lblProgressAll = new JLabel("Overall: ");
JLabel lblProgressCurrent = new JLabel("Current File: ");
progressAll = new JProgressBar(0, 100);
progressAll.setStringPainted(true);
progressCurrent = new JProgressBar(0, 100);
progressCurrent.setStringPainted(true);
txtDetails = new JTextArea(5, 50);
txtDetails.setEditable(false);
DefaultCaret caret = (DefaultCaret) txtDetails.getCaret();
caret.setUpdatePolicy(DefaultCaret.ALWAYS_UPDATE);
JScrollPane scrollPane = new JScrollPane(txtDetails, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
btnCopy = new JButton("Copy");
btnCopy.setFocusPainted(false);
btnCopy.setEnabled(false);
btnCopy.addActionListener(this);
DocumentListener listener = new DocumentListener()
{
@Override
public void removeUpdate(DocumentEvent e)
{
boolean bEnabled = txtSource.getText().length() > 0 && txtTarget.getText().length() > 0;
btnCopy.setEnabled(bEnabled);
}
@Override
public void insertUpdate(DocumentEvent e)
{
boolean bEnabled = txtSource.getText().length() > 0 && txtTarget.getText().length() > 0;
btnCopy.setEnabled(bEnabled);
}
@Override
public void changedUpdate(DocumentEvent e){}
};
txtSource.getDocument().addDocumentListener(listener);
txtTarget.getDocument().addDocumentListener(listener);
JPanel contentPane = (JPanel) getContentPane();
contentPane.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
JPanel panInputLabels = new JPanel(new BorderLayout(0, 5));
JPanel panInputFields = new JPanel(new BorderLayout(0, 5));
JPanel panProgressLabels = new JPanel(new BorderLayout(0, 5));
JPanel panProgressBars = new JPanel(new BorderLayout(0, 5));
panInputLabels.add(lblSource, BorderLayout.NORTH);
panInputLabels.add(lblTarget, BorderLayout.CENTER);
panInputFields.add(txtSource, BorderLayout.NORTH);
panInputFields.add(txtTarget, BorderLayout.CENTER);
panProgressLabels.add(lblProgressAll, BorderLayout.NORTH);
panProgressLabels.add(lblProgressCurrent, BorderLayout.CENTER);
panProgressBars.add(progressAll, BorderLayout.NORTH);
panProgressBars.add(progressCurrent, BorderLayout.CENTER);
JPanel panInput = new JPanel(new BorderLayout(0, 5));
panInput.setBorder(BorderFactory.createCompoundBorder(BorderFactory.createTitledBorder("Input"), BorderFactory.createEmptyBorder(5, 5, 5, 5)));
JPanel panProgress = new JPanel(new BorderLayout(0, 5));
panProgress.setBorder(BorderFactory.createCompoundBorder(BorderFactory.createTitledBorder("Progress"), BorderFactory.createEmptyBorder(5, 5, 5, 5)));
JPanel panDetails = new JPanel(new BorderLayout());
panDetails.setBorder(BorderFactory.createCompoundBorder(BorderFactory.createTitledBorder("Details"), BorderFactory.createEmptyBorder(5, 5, 5, 5)));
JPanel panControls = new JPanel(new BorderLayout());
panControls.setBorder(BorderFactory.createEmptyBorder(5, 0, 5, 0));
panInput.add(panInputLabels, BorderLayout.LINE_START);
panInput.add(panInputFields, BorderLayout.CENTER);
panProgress.add(panProgressLabels, BorderLayout.LINE_START);
panProgress.add(panProgressBars, BorderLayout.CENTER);
panDetails.add(scrollPane, BorderLayout.CENTER);
panControls.add(btnCopy, BorderLayout.CENTER);
JPanel panUpper = new JPanel(new BorderLayout());
panUpper.add(panInput, BorderLayout.NORTH);
panUpper.add(panProgress, BorderLayout.SOUTH);
contentPane.add(panUpper, BorderLayout.NORTH);
contentPane.add(panDetails, BorderLayout.CENTER);
contentPane.add(panControls, BorderLayout.SOUTH);
pack();
setLocationRelativeTo(null);
}
@Override
public void actionPerformed(ActionEvent e)
{
if("Copy".equals(btnCopy.getText()))
{
File source = new File(txtSource.getText());
File target = new File(txtTarget.getText());
if(!source.exists())
{
JOptionPane.showMessageDialog(this, "The source file/directory does not exist!", "ERROR", JOptionPane.ERROR_MESSAGE);
return;
}
if(!target.exists() && source.isDirectory()) target.mkdirs();
else
{
int option = JOptionPane.showConfirmDialog(this, "The target file/directory already exists, do you want to overwrite it?", "Overwrite the target", JOptionPane.YES_NO_OPTION);
if(option != JOptionPane.YES_OPTION) return;
}
task = this.new CopyTask(source, target);
task.addPropertyChangeListener(this);
task.execute();
btnCopy.setText("Cancel");
}
else if("Cancel".equals(btnCopy.getText()))
{
task.cancel(true);
btnCopy.setText("Copy");
}
}
@Override
public void propertyChange(PropertyChangeEvent evt)
{
if("progress".equals(evt.getPropertyName()))
{
int progress = (Integer) evt.getNewValue();
progressAll.setValue(progress);
}
}
public static void main(String[] args)
{
SwingUtilities.invokeLater(new Runnable()
{
@Override
public void run()
{
new FileCopierUtility().setVisible(true);
}
});
}
class CopyTask extends SwingWorker<Void, Integer>
{
private File source;
private File target;
private long totalBytes = 0L;
private long copiedBytes = 0L;
public CopyTask(File source, File target)
{
this.source = source;
this.target = target;
progressAll.setValue(0);
progressCurrent.setValue(0);
}
@Override
public Void doInBackground() throws Exception
{
txtDetails.append("Retrieving some info ... ");
retrieveTotalBytes(source);
txtDetails.append("Done!\n");
copyFiles(source, target);
return null;
}
@Override
public void process(List<Integer> chunks)
{
for(int i : chunks)
{
progressCurrent.setValue(i);
}
}
@Override
public void done()
{
setProgress(100);
btnCopy.setText("Copy");
}
private void retrieveTotalBytes(File sourceFile)
{
File[] files = sourceFile.listFiles();
for(File file : files)
{
if(file.isDirectory()) retrieveTotalBytes(file);
else totalBytes += file.length();
}
}
private void copyFiles(File sourceFile, File targetFile) throws IOException
{
if(sourceFile.isDirectory())
{
if(!targetFile.exists()) targetFile.mkdirs();
String[] filePaths = sourceFile.list();
for(String filePath : filePaths)
{
File srcFile = new File(sourceFile, filePath);
File destFile = new File(targetFile, filePath);
copyFiles(srcFile, destFile);
}
}
else
{
txtDetails.append("Copying " + sourceFile.getAbsolutePath() + " ... ");
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(sourceFile));
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(targetFile));
long fileBytes = sourceFile.length();
long soFar = 0L;
int theByte;
while((theByte = bis.read()) != -1)
{
bos.write(theByte);
setProgress((int) (copiedBytes++ * 100 / totalBytes));
publish((int) (soFar++ * 100 / fileBytes));
}
bis.close();
bos.close();
publish(100);
txtDetails.append("Done!\n");
}
}
}
}
答案 1 :(得分:4)
要实现此目的,您必须提前计算复制操作的数量。您没有包含copyFolder方法,但我认为您希望执行递归复制。 如果是这样,您必须遍历整个目录树以确定要复制的文件数量。在处理大型目录结构时,这可能会让用户讨厌。 (这就是为什么现代操作系统经常显示烦人的&#34;准备在操作开始并显示进度之前复制...&#34; - 消息)
答案 2 :(得分:4)
显示文件的进度非常简单......
long expectedBytes = src.length(); // This is the number of bytes we expected to copy..
byte[] buffer = new byte[1024];
int length;
long totalBytesCopied = 0; // This will track the total number of bytes we've copied
while ((length = in.read(buffer)) > 0){
out.write(buffer, 0, length);
totalBytesCopied += length;
int progress = (int)Math.round(((double)totalBytesCopied / (double)expectedBytes) * 100);
setProgress(progress); // From SwingWorker
}
如果要提供有关要复制/已开始复制的总字节数的信息,则会变得有点复杂。
你有选择。您要么预先扫描所有文件夹(我将文件放入某种队列)并计算要复制的文件的总字节数/数量。然后开始实际的复制过程。
更新此进程非常简单,除非您要累计在整个过程中复制的总字节数而不是单个文件。
... OR
您可以使用生产者/消费者算法。我们的想法是创建一个线程/工作者,其唯一的职责是扫描文件夹以查找要复制的文件,并将它们放入中央/共享队列(这是生产者)。
你会有第二个线程/工作人员弹出这个队列的下一个项目(阻塞到一个新文件变得可用)并且实际上会复制该文件。
这里的技巧是让队列维持一个计数器,使其与通过它的文件和字节总数保持一致,这样你就可以调整整个工作的持续进度......