进度条无效的文件复制

时间:2013-11-24 05:03:17

标签: c# windows winforms

我正在创建一个应用,我使用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;
        }
    }
}

1 个答案:

答案 0 :(得分:1)

首先,您确定文件大小/长度的方式不正确,因为您使用的是文件名本身的字符长度。要使用文件大小:

FileInfo fileInfo = new FileInfo(sfd.FileName);
intOutputFileSize = fileInfo.Length;

其次,File.Copy将一次性复制文件,这意味着您无法循环复制尝试以您当前的方式显示progess栏。

要显示进度,您必须使用FileStream来读取源文件并写入目标文件(自行复制)。

通过这种方式,您可以编写字节块并在执行此操作时计算出进度。