Создать макет папки с большим количеством файлов - PullRequest
2 голосов
/ 30 января 2020

Я создаю приложение, которое берет sourcePath и создает его пустышку на destinationPath.

Я имею в виду, что хочу скопировать структуру папки и ее файлов , однако файлы должны быть пустыми, чтобы это можно было сделать быстро (я хочу копировать до 700000 файлов за раз, поэтому скорость очень важна)

Кто-нибудь знает, как go об этом? вот что я написал до сих пор (он только копирует структуру папок, без файлов)

 private void button1_Click(object sender, EventArgs e)
        {
            string sourcePath = textBox1.Text;
            string destinationPath = textBox2.Text;

            string cmdCopyFolderTree = $@"/C xcopy /t /e {sourcePath} {destinationPath} ";

            System.Diagnostics.Process.Start("CMD.exe",cmdCopyFolderTree);
            Console.WriteLine();
        }

Ответы [ 3 ]

2 голосов
/ 30 января 2020

Хорошо, вот нерекурсивное решение с многопоточностью:

  • Мы полагаемся на EnumerateFileSystemEntries, чтобы рекурсивно получить все в заданной папке.
  • Мы разбить каждый путь на две группы: папки и файлы.
  • Мы создаем все папки параллельно в фиктивной папке
  • Мы создаем все файлы параллельно в фиктивной папке

Код:

public static async Task Main()
{
    var oldPath = "foo"; // folder to copy
    var newPath = "dummy"; // folder to create dummies

    var oldDirectory = Path.GetFullPath(oldPath);
    var oldDirectoryParent = Path.GetDirectoryName(oldDirectory);
    var newDirectory = Path.Combine(oldDirectoryParent, newPath);
    Directory.CreateDirectory(newDirectory);

    var paths = Directory.EnumerateFileSystemEntries(oldDirectory, "*.*", SearchOption.AllDirectories);
    var filesAndFolders = paths.ToLookup(Directory.Exists);

    var directoryTasks = filesAndFolders[true]
        .Select(path => newDirectory + path.Substring(oldDirectory.Length))
        .Select(CreateDirectoryAsync);
    await Task.WhenAll(directoryTasks);

    var fileTasks = filesAndFolders[false]
        .Select(path => newDirectory + path.Substring(oldDirectory.Length))
        .Select(CreateAsync);
    await Task.WhenAll(fileTasks);
}

public static Task<FileStream> CreateAsync(string path) => Task.Run(() => File.Create(path));
public static Task<DirectoryInfo> CreateDirectoryAsync(string path) => Task.Run(() => Directory.CreateDirectory(path));

Попробуйте онлайн!

1 голос
/ 30 января 2020

Попробуйте:

private void RecursiveCreation(DirectoryInfo dir, string destination, string subPath = "")
{
    foreach (var subdir in dir.GetDirectories())
    {
        string dirPath = Path.Combine(subPath, subdir.Name);
        Directory.CreateDirectory(Path.Combine(destination, dirPath));
        RecursiveCreation(subdir, destination, dirPath);
    }

    foreach (var file in dir.GetFiles())
    {
        File.Create(Path.Combine(destination, subPath, file.Name));
    }
}

Использование:

RecursiveCreation(new DirectoryInfo(sourcePath), destinationPath);
1 голос
/ 30 января 2020

Класс каталога имеет функции GetFiles () и GetDirectories (), с примером рекурсии:

https://docs.microsoft.com/en-us/dotnet/api/system.io.directory.getfiles

Обычно операции на диске связаны с диском, но я не уверен на 100% в этом случае. Ваша операция будет влиять только на таблицы файлов / каталогов без фактической записи большого количества данных на диск. И AFAIK, эти таблицы кэшируются в памяти, потому что они фундаментальны.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...