复制目录的性能

时间:2012-04-04 15:29:04

标签: c# performance copy

我正在使用C#将文件从一个目录复制到另一个目录。 我正在使用msdn的代码,但它花了一分钟左右的时间很慢 复制几个演出。在资源管理器中只需几秒钟。 http://channel9.msdn.com/Forums/TechOff/257490-How-Copy-directories-in-C Surly有一种更快的方式.. :)

        private static void Copy(string sourceDirectory, string targetDirectory)
    {
        DirectoryInfo diSource = new DirectoryInfo(sourceDirectory);
        DirectoryInfo diTarget = new DirectoryInfo(targetDirectory);

        CopyAll(diSource, diTarget);
    }

    private static void CopyAll(DirectoryInfo source, DirectoryInfo target)
    {
        // Check if the target directory exists, if not, create it.
        if (Directory.Exists(target.FullName) == false)
        {
            Directory.CreateDirectory(target.FullName);
        }

        // Copy each file into it's new directory.
        foreach (FileInfo fi in source.GetFiles())
        {
            fi.CopyTo(Path.Combine(target.ToString(), fi.Name), true);
        }

        // Copy each subdirectory using recursion.
        foreach (DirectoryInfo diSourceSubDir in source.GetDirectories())
        {
            DirectoryInfo nextTargetSubDir =
                target.CreateSubdirectory(diSourceSubDir.Name);
            CopyAll(diSourceSubDir, nextTargetSubDir);
        }
    }

使用Parallel我能够在比探索器和xcopy快一分钟内复制6gig。


private static void CopyAll(string SourcePath, string DestinationPath)
{
    string[] directories = System.IO.Directory.GetDirectories(SourcePath, "*.*", SearchOption.AllDirectories);

    Parallel.ForEach(directories, dirPath =>
    {
        Directory.CreateDirectory(dirPath.Replace(SourcePath, DestinationPath));
    }); 

    string[] files = System.IO.Directory.GetFiles(SourcePath, "*.*", SearchOption.AllDirectories);

    Parallel.ForEach(files, newPath =>
    {
        File.Copy(newPath, newPath.Replace(SourcePath, DestinationPath));
    }); 
}

4 个答案:

答案 0 :(得分:5)

你使用的是递归。它总是会减慢系统的速度。

使用它,因为它没有递归。

void CopyAll (string SourcePath, string DestinationPath)
{
    //Now Create all of the directories
    foreach (string dirPath in Directory.GetDirectories(SourcePath, "*.*", 
    SearchOption.AllDirectories))
    Directory.CreateDirectory(dirPath.Replace(SourcePath, DestinationPath));

    //Copy all the files
    foreach (string newPath in Directory.GetFiles(SourcePath, "*.*", 
    SearchOption.AllDirectories))
    File.Copy(newPath, newPath.Replace(SourcePath, DestinationPath));
}

答案 1 :(得分:0)

您的问题可能是*文件的覆盖。 我看到你打电话了

fi.CopyTo(Path.Combine(target.ToString(), fi.Name), true);

其中true表示覆盖文件(如果存在)。

基于此我假设,以便您的应用程序覆盖现有文件。

如果你

那么东西会更快
  • 首先使用一些临时唯一名称重命名目标目录
  • 只是将源复制到dest(所以没有覆盖)

如果成功删除临时目录,如果失败删除所有复制的文件并将temp重命名为其原始名称。

应该更快。

祝你好运。

答案 2 :(得分:0)

我怀疑@Oded是正确的,你正在将副本与移动进行比较。

如果你想确保你所做的事情和shell一样,你可以查看SHFileOperation或(在Vista或更新版本上)IFileOperation。至少据我所知,你必须通过P / Invoke使用SHFileOperation。 IFileOperation是一个COM接口。

答案 3 :(得分:0)

使用Parallel.ForEach循环创建目录存在一个很大的问题,首先需要注意的是,嵌套在其他目录中的子目录,如果Parallel无序地创建目录,则代码可能会被抛出尝试创建目录级别8而目录级别6甚至尚未生成。