我想使用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>
我担心这不是一个非常简洁的解决方案,因为对我来说两次循环似乎并不合适。另外,如果源文件夹中有太多不同的文件和子文件夹,我不确定我的字典是否可以存储那么多信息。
有没有更好的选择?
答案 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;
}