带进度条的文件复制 [英] File Copy with Progress Bar
问题描述
我使用了这个代码:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Windows.Forms;
using System.IO;
namespace WindowsApplication1 {
public partial class Form1 : Form {
// Class to report progress
private class UIProgress {
public UIProgress(string name_, long bytes_, long maxbytes_) {
name = name_; bytes = bytes_; maxbytes = maxbytes_;
}
public string name;
public long bytes;
public long maxbytes;
}
// Class to report exception {
private class UIError {
public UIError(Exception ex, string path_) {
msg = ex.Message; path = path_; result = DialogResult.Cancel;
}
public string msg;
public string path;
public DialogResult result;
}
private BackgroundWorker mCopier;
private delegate void ProgressChanged(UIProgress info);
private delegate void CopyError(UIError err);
private ProgressChanged OnChange;
private CopyError OnError;
public Form1() {
InitializeComponent();
mCopier = new BackgroundWorker();
mCopier.DoWork += Copier_DoWork;
mCopier.RunWorkerCompleted += Copier_RunWorkerCompleted;
mCopier.WorkerSupportsCancellation = true;
OnChange += Copier_ProgressChanged;
OnError += Copier_Error;
button1.Click += button1_Click;
ChangeUI(false);
}
private void Copier_DoWork(object sender, DoWorkEventArgs e) {
// Create list of files to copy
string[] theExtensions = { "*.jpg", "*.jpeg", "*.bmp", "*.png", "*.gif" };
List<FileInfo> files = new List<FileInfo>();
string path = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
DirectoryInfo dir = new DirectoryInfo(path);
long maxbytes = 0;
foreach (string ext in theExtensions) {
FileInfo[] folder = dir.GetFiles(ext, SearchOption.AllDirectories);
foreach (FileInfo file in folder) {
if ((file.Attributes & FileAttributes.Directory) != 0) continue;
files.Add(file);
maxbytes += file.Length;
}
}
// Copy files
long bytes = 0;
foreach (FileInfo file in files) {
try {
this.BeginInvoke(OnChange, new object[] { new UIProgress(file.Name, bytes, maxbytes) });
File.Copy(file.FullName, @"c: emp" + file.Name, true);
}
catch (Exception ex) {
UIError err = new UIError(ex, file.FullName);
this.Invoke(OnError, new object[] { err });
if (err.result == DialogResult.Cancel) break;
}
bytes += file.Length;
}
}
private void Copier_ProgressChanged(UIProgress info) {
// Update progress
progressBar1.Value = (int)(100.0 * info.bytes / info.maxbytes);
label1.Text = "Copying " + info.name;
}
private void Copier_Error(UIError err) {
// Error handler
string msg = string.Format("Error copying file {0}
{1}
Click OK to continue copying files", err.path, err.msg);
err.result = MessageBox.Show(msg, "Copy error", MessageBoxButtons.OKCancel, MessageBoxIcon.Exclamation);
}
private void Copier_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) {
// Operation completed, update UI
ChangeUI(false);
}
private void ChangeUI(bool docopy) {
label1.Visible = docopy;
progressBar1.Visible = docopy;
button1.Text = docopy ? "Cancel" : "Copy";
label1.Text = "Starting copy...";
progressBar1.Value = 0;
}
private void button1_Click(object sender, EventArgs e) {
bool docopy = button1.Text == "Copy";
ChangeUI(docopy);
if (docopy) mCopier.RunWorkerAsync();
else mCopier.CancelAsync();
}
}
}
发布在这里(nobugz 发布的那个)复制文件并在进度条中显示状态.
posted here (the one that nobugz posted) in copying files and displaying the status in progress bar.
我想在复制时不断增加进度条的值,尤其是大文件.在此示例代码中发生的情况是进度条中的值在复制的每个文件上停止,并且在复制一个文件后,它将增加到要复制的下一个文件的大小.我希望它像 Windows 中的 CopyFileEx
一样工作,复制时进度条会不断增加(我不能使用 CopyFileEx
,因为我想拥有自己的实现).
I wanted to continuously increment the value of the progress bar while copying, especially large files. What happens in this sample code is that the value in progress bar stops on every file copied and after one file has been copied it will then increment to the size of the next file to be copied. I wanted it to work like CopyFileEx
in Windows that progress bar continuously increment when copying (I cant use CopyFileEx
because I wanted to have my own implementation).
推荐答案
你需要这样的东西:
public delegate void ProgressChangeDelegate(double Percentage, ref bool Cancel);
public delegate void Completedelegate();
class CustomFileCopier
{
public CustomFileCopier(string Source, string Dest)
{
this.SourceFilePath = Source;
this.DestFilePath = Dest;
OnProgressChanged += delegate { };
OnComplete += delegate { };
}
public void Copy()
{
byte[] buffer = new byte[1024 * 1024]; // 1MB buffer
bool cancelFlag = false;
using (FileStream source = new FileStream(SourceFilePath, FileMode.Open, FileAccess.Read))
{
long fileLength = source.Length;
using (FileStream dest = new FileStream(DestFilePath, FileMode.CreateNew, FileAccess.Write))
{
long totalBytes = 0;
int currentBlockSize = 0;
while ((currentBlockSize = source.Read(buffer, 0, buffer.Length)) > 0)
{
totalBytes += currentBlockSize;
double percentage = (double)totalBytes * 100.0 / fileLength;
dest.Write(buffer, 0, currentBlockSize);
cancelFlag = false;
OnProgressChanged(percentage, ref cancelFlag);
if (cancelFlag == true)
{
// Delete dest file here
break;
}
}
}
}
OnComplete();
}
public string SourceFilePath { get; set; }
public string DestFilePath { get; set; }
public event ProgressChangeDelegate OnProgressChanged;
public event Completedelegate OnComplete;
}
只需在单独的线程中运行它并订阅 OnProgressChanged
事件.
Just run it in separate thread and subscribe for OnProgressChanged
event.
这篇关于带进度条的文件复制的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!