Поиск в C Sharp с помощью регулярных выражений - PullRequest
3 голосов
/ 10 марта 2011

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

В настоящее время этот поиск занимает около 50 минут с использованием текущего метода из-за количества папок, расположенных в этом каталоге.

private void ProcessFiles(string path, string searchPattern)
{
    string pattern = @"^(\\\\server\\folder1\\subfolder\\(MENS|WOMENS|MENS\sDROPBOX|WOMENS\sDROPBOX)\\((((COLOR\sCHIPS)|(ALL\sMENS\sCOLORS)))|((\d{4})\\(\w+)\\(FINAL\sART|FINAL\sARTWORK)\\(\d{3}))))$";
    DirectoryInfo di = new DirectoryInfo(path);
    try
    {
        Debug.WriteLine("I'm in " + di.FullName);
        if (di.Exists)
        {
            DirectoryInfo[] dirs = di.GetDirectories("*", SearchOption.TopDirectoryOnly);
            foreach (DirectoryInfo d in dirs)
            {
                string[] splitPath = d.FullName.Split('\\');


                var dirMatch = new Regex(pattern, RegexOptions.IgnoreCase);

                if (dirMatch.IsMatch(d.FullName))
                {
                    Debug.WriteLine("---Processing Directory: " + d.FullName + " ---");
                    FileInfo[] files = d.GetFiles(searchPattern, SearchOption.TopDirectoryOnly);
                    AddColor(files, splitPath);
                }
                ProcessFiles(d.FullName, searchPattern);
            }
        }


    }
    catch (Exception e)
    {

    }

}

Ответы [ 3 ]

7 голосов
/ 10 марта 2011

Я бы использовал что-то вроде следующего, нет необходимости в рекурсии, пусть BCL сделает это за вас:

// I didn't recount the parenetheses...
Regex re = new Regex("MENS|WOMENS|MENS\sDROPBOX|WOMENS\sDROPBOX)\\((((COLOR\sCHIPS)|(ALL\sMENS\sCOLORS)))|((\d{4})\\(\w+)\\(FINAL\sART|FINAL\sARTWORK)\\(\d{3})))");
var dirs = from dir in 
           Directory.EnumerateDirectories(dirPath, "dv_*",
           SearchOption.AllDirectories)
           where re.IsMatch(dir)
           select dir;

Если он все еще работает 50 минут, значит, вы работаете на медленном диске, в сети или аналогичном.

РЕДАКТИРОВАТЬ: вы редактировали свой вопрос. Это ясно показывает, что вы выполняете свой код по пути UNC. Это очень медленно, если вам нужна скорость, запустите его на этом сервере.

Примечание: есть большая разница между поведением GetDirectories (которое вы используете) и EnumerateDirectories. Документация Microsoft говорит об этом :

Методы EnumerateDirectories и GetDirectories отличаются следующим образом: когда вы используете EnumerateDirectories, вы можете начать перечисление коллекции имен до того, как будет возвращена вся коллекция; когда вы используете GetDirectories, вы должны подождать, пока весь массив имен будет возвращен, прежде чем вы сможете получить доступ к массиву. Поэтому, когда вы работаете со многими файлами и каталогами, EnumerateDirectories могут быть более эффективными.

Что касается вашего вопроса: он будет проходить через все каталоги, к которым у него есть доступ, не позволяйте ему запускаться в каталоге, к которому у вас нет доступа (это вызовет исключение).

0 голосов
/ 10 марта 2011

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

0 голосов
/ 10 марта 2011

Чтобы получить самые быстрые результаты в дереве каталогов, лучше всего использовать взаимодействие. FindFirstFile, FindNextFile, FindClose - ваши друзья.

http://msdn.microsoft.com/en-us/library/aa364418%28v=vs.85%29.aspx

Но не ожидайте скорости света, если вам нужно пересечь огромное дерево.

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