首先从目录复制最小的文件

时间:2016-09-24 15:53:55

标签: c# algorithm sorting dictionary copy

我想使用Visual C#.NET版本3.5将目录中的所有文件复制到目标文件夹,这可以很容易地完成(取自this回答):

private static void Copy(string sourceDir, string targetDir)
{
    Directory.CreateDirectory(targetDir);

    foreach (var file in Directory.GetFiles(sourceDir))
        File.Copy(file, Path.Combine(targetDir, Path.GetFileName(file)));

    foreach (var directory in Directory.GetDirectories(sourceDir))
        Copy(directory, Path.Combine(targetDir, Path.GetFileName(directory)));
}

现在,这里有一个小问题:我希望它首先对所有文件进行排序,所以如果源路径是一个可移动的驱动器,它会在一段时间后插入,它仍然会有大多数可能的数据复制。使用上层算法,如果它首先包含一个包含大文件的目录,然后继续使用包含许多较小文件的目录,那么当软件仍在复制大文件时,用户可能会将其驱动器插入,并且不会留下任何内容在驱动器上除了不完整的大文件。

我的想法是做多个循环:首先,每个文件路径都会被放入包含其大小的字典中,然后这个字典将被排序,然后每个文件将从源复制到目标(包括文件夹创建)。 / p>

我担心这不是一个非常简洁的解决方案,因为对我来说两次循环似乎并不合适。另外,如果源文件夹中有太多不同的文件和子文件夹,我不确定我的字典是否可以存储那么多信息。

有没有更好的选择?

2 个答案:

答案 0 :(得分:3)

你可以使用一个更简单的方法,因为你可以在不使用递归的情况下获取目录子树中的所有文件。

问题的缺失部分是文件大小。可以使用DirectoryInfo类和FileInfo类获取此信息,而排序只是应用于文件序列的Linq指令,如以下示例所示。

private static void Copy(string sourceDir, string targetDir)
{
    DirectoryInfo di = new DirectoryInfo(sourceDir);
    foreach (FileInfo fi in di.GetFiles("*.*", SearchOption.AllDirectories).OrderBy(d => d.Length))
    {
        string leftOver = fi.DirectoryName.Replace(sourceDir, "");
        string destFolder = Path.Combine(targetDir, leftOver);

        // Because the files are listed in order by size
        // we could copy a file deep down in the subtree before the 
        // ones at the top of the sourceDir

        // Luckily CreateDirectory doesn't throw if the directory exists
        // and automatically creates all the intermediate folders required
        Directory.CreateDirectory(destFolder);

        // Just write the intended copy parameters as a proof of concept
        Console.WriteLine($"{fi.Name} with size = {fi.Length} -> Copy from {fi.DirectoryName} to {Path.Combine(destFolder, fi.Name)}");
    }
}

在这个例子中,我使用Console.WriteLine更改了File.Copy方法只是为了获得概念证明而不复制任何东西,但替换是微不足道的。

另请注意,最好使用EnumerateFiles代替GetFiles作为explained in the MSDN documentation

答案 1 :(得分:2)

我希望这有帮助!

首先;获取源目录中的所有文件,递归是可选的。然后继续将按大小排序的所有文件复制到目标目录。

void CopyFiles(string sourceDir, string targetDir, bool recursive = false)
{
    foreach (var file in GetFiles(sourceDir, recursive).OrderBy(f => f.Length))
    {
        var subDir = file.DirectoryName
            .Replace(sourceDir, String.Empty)
            .TrimStart(Path.DirectorySeparatorChar);
        var fullTargetDir = Path.Combine(targetDir, subDir);

        if (!Directory.Exists(fullTargetDir))
            Directory.CreateDirectory(fullTargetDir);

        file.CopyTo(Path.Combine(fullTargetDir, file.Name));
    }
}

IEnumerable<FileInfo> GetFiles(string directory, bool recursive)
{
    var files = new List<FileInfo>();

    if (recursive)
    {
        foreach (var subDirectory in Directory.GetDirectories(directory))
            files.AddRange(GetFiles(subDirectory, true));
    }

    foreach (var file in Directory.GetFiles(directory))
        files.Add(new FileInfo(file));

    return files;
}