我正在创建一个应用,我使用OpenFileDialog
选择文件,将名称放入文本框,然后我会打开SaveFileDialog
以选择其他位置(如以及不同的文件名,如有必要)。当我单击按钮复制文件时,我正在使用带有进度条的System.IO.File.Copy(<input file name>,<output file name>,<overwrite true/false>)
。即使我在单独的线程上运行副本,文件也会立即复制(甚至到网络位置),并且应用程序在复制时会冻结。此外,进度条永远不会移动。其他人已经回答了类似的问题,但我不太了解C#知道如何将这些答案应用于我的代码,而且我不知道我做错了什么。
我的代码如下(我从主窗体中输入了整个代码,以便更容易理解流程):
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;
namespace FileProgress
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
// Declare variables here.
OpenFileDialog ofd = new OpenFileDialog();
SaveFileDialog sfd = new SaveFileDialog();
FolderBrowserDialog fbd = new FolderBrowserDialog();
BackgroundWorker bgWorker = new BackgroundWorker();
string strInputFile;
string strOutputFile;
int intInputFileSize;
int intOutputFileSize;
int intFileProgress;
private void Form1_Load(object sender, EventArgs e)
{
// Set up the form with defaults.
txtInputFile.Text = "Please select a file.";
txtInputFile.ForeColor = Color.Gray;
txtOutputFile.Text = "Please select the location you want to copy the file to.";
txtOutputFile.ForeColor = Color.Gray;
}
private void txtInputFile_MouseClick(object sender, MouseEventArgs e)
{
// This will blank out the txtInputFile textbox when clicked.
if (txtInputFile.Text == "Please select a file.")
{
txtInputFile.Text = "";
}
// This will put text into the txtOutputFile textbox, if it is blank.
if (txtOutputFile.Text == "")
{
txtOutputFile.Text = "Please select the location you want to copy the file to.";
}
}
private void txtOutputFile_MouseClick(object sender, MouseEventArgs e)
{
// This will blank out the txtOutputFile textbox when clicked.
if (txtOutputFile.Text == "Please select the location you want to copy the file to.")
{
txtOutputFile.Text = "";
}
// This will put text into the txtInputFile textbox, if it is blank.
if (txtInputFile.Text == "")
{
txtInputFile.Text = "Please select a file.";
}
}
private void btnInputFile_Click(object sender, EventArgs e)
{
// Here we open the OpenFileDialog (ofd) and select the file we want to copy.
// Change the text color in the textbox to black.
txtInputFile.ForeColor = Color.Black;
ofd.FileName = String.Empty;
// Set the initial directory.
ofd.InitialDirectory = "%HOMEPATH%";
ofd.Title = "Select a file";
// We want to be able to open any type of file.
ofd.Filter = "All files (*.*)|*.*";
if (ofd.ShowDialog() == DialogResult.OK)
{
// Set the filename as the text of the textbox txtInputFile.
strInputFile = ofd.FileName;
txtInputFile.Text = strInputFile;
// Get the length of the file.
//This seems to be getting the number of characters in the path and filename.
intInputFileSize = strInputFile.Length;
// Enable the Copy button.
btnCopy.Enabled = true;
}
}
private void btnOutputFile_Click(object sender, EventArgs e)
{
// Here we open the SaveFileDialog (sfd) and select the location where we want to copy the file to.
// Change the text color in the textbox to black.
txtOutputFile.ForeColor = Color.Black;
sfd.FileName = txtInputFile.Text;
//We want to see all files
sfd.Filter = "All files (*.*)|*.*";
sfd.FilterIndex = 2;
sfd.RestoreDirectory = true;
if (sfd.ShowDialog() == DialogResult.OK)
{
// Set the text of the txtOutputFile textbox.
txtOutputFile.Text = sfd.FileName;
strOutputFile = sfd.FileName;
// Get the size of the file for debugging purposes.
//This seems to be getting the number of characters in the path and filename.
intOutputFileSize = strOutputFile.Length;
}
}
private void btnCopy_Click(object sender, EventArgs e)
{
// We call the background worker to do work on a separate thread.
bgWorker.RunWorkerAsync();
// Initialize the the DoWork Event Handler.
bgWorker.DoWork += new DoWorkEventHandler(bgWorker_DoWork);
}
private void bgWorker_DoWork(object sender, DoWorkEventArgs e)
{
// We need to convert the file's size to a percentage.
intFileProgress = intInputFileSize / 100;
// Increment the progress bar for each percentage of the file that is copied.
for (int i = 0; i < (intFileProgress); i++)
{
// Actually copy the file.
File.Copy(strInputFile, strOutputFile, true);
// Tell the system that the background worker will be reporting progress, and then, actually report the progress.
bgWorker.WorkerReportsProgress = true;
bgWorker.ReportProgress(intFileProgress);
}
}
private void bgWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
// We will increase the progress bar when work progress is reported.
pbCopyProgress.Value = e.ProgressPercentage;
pbCopyProgress.Text = (e.ProgressPercentage.ToString() + "%");
}
private void bgWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
// Disable the Copy button once the file has been copied. The messagebox is for debugging only.
MessageBox.Show("The file " + strOutputFile + " (" + Convert.ToString(intOutputFileSize) + ") has been copied", "Message");
btnCopy.Enabled = false;
}
}
}
答案 0 :(得分:1)
首先,您确定文件大小/长度的方式不正确,因为您使用的是文件名本身的字符长度。要使用文件大小:
FileInfo fileInfo = new FileInfo(sfd.FileName);
intOutputFileSize = fileInfo.Length;
其次,File.Copy将一次性复制文件,这意味着您无法循环复制尝试以您当前的方式显示progess栏。
要显示进度,您必须使用FileStream来读取源文件并写入目标文件(自行复制)。
通过这种方式,您可以编写字节块并在执行此操作时计算出进度。