6

我最近不得不从使用更改File.Copy()CopyFileEx,我正在努力寻找如何使用它。

经过大量谷歌搜索后,我发现这个不错的包装器可以使用它,但我需要的是获取当前文件的复制字节的进度,如果可能的话,计算复制我传递给它的所有文件的进度。

(我知道有些项目链接了进度条,CopyFileEx但我没有足够的经验来提取相关代码,我想使用这个包装器)。

大概只是通过将它与要复制的文件的总字节数进行比较,我会事先找到,并从中计算出百分比。

我目前的复制方法是

FileRoutines.CopyFile(new FileInfo("source.txt"), new FileInfo("dest.txt"));

我坚持的是如何使用获取进度信息所需的参数来重载它。

public sealed class FileRoutines
{
    public static void CopyFile(FileInfo source, FileInfo destination)
    {
        CopyFile(source, destination, CopyFileOptions.None);
    }

    public static void CopyFile(FileInfo source, FileInfo destination, 
        CopyFileOptions options)
    {
        CopyFile(source, destination, options, null);
    }

    public static void CopyFile(FileInfo source, FileInfo destination, 
        CopyFileOptions options, CopyFileCallback callback)
    {
        CopyFile(source, destination, options, callback, null);
    }

    public static void CopyFile(FileInfo source, FileInfo destination, 
        CopyFileOptions options, CopyFileCallback callback, object state)
    {
        if (source == null) throw new ArgumentNullException("source");
        if (destination == null) 
            throw new ArgumentNullException("destination");
        if ((options & ~CopyFileOptions.All) != 0) 
            throw new ArgumentOutOfRangeException("options");

        new FileIOPermission(
            FileIOPermissionAccess.Read, source.FullName).Demand();
        new FileIOPermission(
            FileIOPermissionAccess.Write, destination.FullName).Demand();

        CopyProgressRoutine cpr = callback == null ? 
            null : new CopyProgressRoutine(new CopyProgressData(
                source, destination, callback, state).CallbackHandler);

        bool cancel = false;
        if (!CopyFileEx(source.FullName, destination.FullName, cpr, 
            IntPtr.Zero, ref cancel, (int)options))
        {
            throw new IOException(new Win32Exception().Message);
        }
    }

    private class CopyProgressData
    {
        private FileInfo _source = null;
        private FileInfo _destination = null;
        private CopyFileCallback _callback = null;
        private object _state = null;

        public CopyProgressData(FileInfo source, FileInfo destination, 
            CopyFileCallback callback, object state)
        {
            _source = source; 
            _destination = destination;
            _callback = callback;
            _state = state;
        }

        public int CallbackHandler(
            long totalFileSize, long totalBytesTransferred, 
            long streamSize, long streamBytesTransferred, 
            int streamNumber, int callbackReason,
            IntPtr sourceFile, IntPtr destinationFile, IntPtr data)
        {
            return (int)_callback(_source, _destination, _state, 
                totalFileSize, totalBytesTransferred);
        }
    }

    private delegate int CopyProgressRoutine(
        long totalFileSize, long TotalBytesTransferred, long streamSize, 
        long streamBytesTransferred, int streamNumber, int callbackReason,
        IntPtr sourceFile, IntPtr destinationFile, IntPtr data);

    [SuppressUnmanagedCodeSecurity]
    [DllImport("Kernel32.dll", CharSet=CharSet.Auto, SetLastError=true)]
    private static extern bool CopyFileEx(
        string lpExistingFileName, string lpNewFileName,
        CopyProgressRoutine lpProgressRoutine,
        IntPtr lpData, ref bool pbCancel, int dwCopyFlags);
}

public delegate CopyFileCallbackAction CopyFileCallback(
    FileInfo source, FileInfo destination, object state, 
    long totalFileSize, long totalBytesTransferred);

public enum CopyFileCallbackAction
{
    Continue = 0,
    Cancel = 1,
    Stop = 2,
    Quiet = 3
}

[Flags]
public enum CopyFileOptions
{
    None = 0x0,
    FailIfDestinationExists = 0x1,
    Restartable = 0x2,
    AllowDecryptedDestination = 0x8,
    All = FailIfDestinationExists | Restartable | AllowDecryptedDestination
}

任何指针都非常感谢。

4

2 回答 2

8

包装器已经拥有处理进度所需的管道。只需在返回之前实现代码以在 CallbackHandler 中更新您的进度条。progressBar1.Maximum 默认为 100,因此下面的代码将计算百分比。

用这个替换你当前的 CopyFile 调用:

CopyFileCallbackAction myCallback(FileInfo source, FileInfo destination, object state, long totalFileSize, long totalBytesTransferred)
{
    double dProgress = (totalBytesTransferred / (double)totalFileSize) * 100.0;
    progressBar1.Value = (int)dProgress;
    return CopyFileCallbackAction.Continue;
}

FileRoutines.CopyFile(new FileInfo("source.txt"), new FileInfo("dest.txt"), myCallback);
于 2012-12-20T16:26:27.700 回答
0

如果您只想显示文件副本的进度条,您可以这样。它使用显示进度条和剩余时间的 Windows 标准对话框,并有一个取消按钮。这正是我在基本上一行代码中所需要的。

// The following using directive requires a project reference to Microsoft.VisualBasic. 
using Microsoft.VisualBasic.FileIO;

class FileProgress
{
    static void Main()
    {
        // Specify the path to a folder that you want to copy. If the folder is small,  
        // you won't have time to see the progress dialog box. 
        string sourcePath = @"C:\Windows\symbols\";
        // Choose a destination for the copied files. 
        string destinationPath = @"C:\TestFolder";

        FileSystem.CopyDirectory(sourcePath, destinationPath,
            UIOption.AllDialogs);
    }
}
于 2016-09-01T14:45:19.690 回答