Подтвердить что ты не робот

Самый быстрый способ в С# найти файл в каталоге с более чем 20 000 файлов

У меня есть работа, которая работает каждую ночь, чтобы вытащить xml файлы из каталога с более чем 20 000 подпапок под корнем. Вот как выглядит структура:

rootFolder/someFolder/someSubFolder/xml/myFile.xml
rootFolder/someFolder/someSubFolder1/xml/myFile1.xml
rootFolder/someFolder/someSubFolderN/xml/myFile2.xml
rootFolder/someFolder1
rootFolder/someFolderN

Итак, глядя на вышеизложенное, структура всегда одна и та же: корневая папка, затем две подпапки, затем каталог xml, а затем xml файл. Мне известно только имя rootFolder и xml-каталога.

Код ниже проходит через все каталоги и очень медленный. Любые рекомендации о том, как я могу оптимизировать поиск, особенно если структура каталогов известна?

string[] files = Directory.GetFiles(@"\\somenetworkpath\rootFolder", "*.xml", SearchOption.AllDirectories);
4b9b3361

Ответ 1

Вместо того, чтобы делать GetFiles и выполнять поиск по грубой силе, вы, скорее всего, можете использовать GetDirectories, сначала получить список "Первая подпапка", пропустить эти каталоги, а затем повторить процесс для подпапки, прокручивая их, наконец, найдите папку xml и, наконец, найдите .xml файлы.

Теперь, что касается производительности, скорость этого будет различной, но сначала поиск каталогов, ТОГДА получение файлов должно очень помочь!

Обновление

Хорошо, я быстро проверил тестирование, и вы можете его оптимизировать гораздо дальше, чем я думал.

Следующий фрагмент кода будет искать структуру каталогов и найти ВСЕ папки "xml" внутри всего дерева каталогов.

string startPath = @"C:\Testing\Testing\bin\Debug";
string[] oDirectories = Directory.GetDirectories(startPath, "xml", SearchOption.AllDirectories);
Console.WriteLine(oDirectories.Length.ToString());
foreach (string oCurrent in oDirectories)
    Console.WriteLine(oCurrent);
Console.ReadLine();

Если вы отбросите это приложение в тестовую консоль, вы увидите, что оно выводит результаты.

Теперь, как только вы это сделаете, просто загляните в каждый найденный каталог для вас .xml файлов.

Ответ 2

Я создал рекурсивный метод GetFolders, используя Parallel.ForEach, чтобы найти все папки, названные в качестве переменной yourKeyword

List<string> returnFolders = new List<string>();
object locker = new object();

Parallel.ForEach(subFolders, subFolder =>
{
    if (subFolder.ToUpper().EndsWith(yourKeyword))
    {
        lock (locker)
        {
            returnFolders.Add(subFolder);
        }
    }
    else
    {
        lock (locker)
        {
            returnFolders.AddRange(GetFolders(Directory.GetDirectories(subFolder)));
        }
    }
});

return returnFolders;

Ответ 3

Существуют ли дополнительные каталоги на том же уровне, что и папка xml? Если это так, возможно, вы можете ускорить поиск, если вы сделаете это самостоятельно, и устраните этот уровень от поиска.

        System.IO.DirectoryInfo root = new System.IO.DirectoryInfo(rootPath);
        List<System.IO.FileInfo> xmlFiles=new List<System.IO.FileInfo>();

        foreach (System.IO.DirectoryInfo subDir1 in root.GetDirectories())
        {
            foreach (System.IO.DirectoryInfo subDir2 in subDir1.GetDirectories())
            {
                System.IO.DirectoryInfo xmlDir = new System.IO.DirectoryInfo(System.IO.Path.Combine(subDir2.FullName, "xml"));

                if (xmlDir.Exists)
                {
                    xmlFiles.AddRange(xmlDir.GetFiles("*.xml"));
                }
            }
        }

Ответ 4

Я не могу думать о чем-то быстрее в С#, но у вас есть индексирование для этой файловой системы?

Ответ 5

Единственный способ, с помощью которого я могу видеть, что имеет большое значение, - это переходить от охоты на грубую силу и использовать некоторую программу индексирования третьей стороны или ОС для ускорения возврата. таким образом поиск выполняется в автономном режиме из вашего приложения.

Но я также предлагаю вам лучше изучить способы структурирования этих данных, если это вообще возможно.

Ответ 6

Используйте P/Invoke на FindFirstFile/FindNextFile/FindClose и избегайте накладных расходов на создание большого количества экземпляров FileInfo.

Но это будет тяжелая работа, чтобы получить право (вам придется делать все, что нужно для управления файлом или каталогом и рекурсией). Поэтому попробуйте что-то простое (Directory.GetFiles(), Directory.GetDirectories()), чтобы начать работу и заставить все работать. Если это слишком медленный взгляд на альтернативы (но всегда измерять, слишком легко сделать это медленнее).