Как быстро проверить, если папка пуста (.NET)? - PullRequest
122 голосов
/ 16 апреля 2009

Я должен проверить, если каталог на диске пуст. Это означает, что он не содержит никаких папок / файлов. Я знаю, что есть простой метод. Мы получаем массив FileSystemInfo и проверяем, равно ли количество элементов нулю. Примерно так:

public static bool CheckFolderEmpty(string path)
{
    if (string.IsNullOrEmpty(path))
    {
        throw new ArgumentNullException("path");
    }

    var folder = new DirectoryInfo(path);
    if (folder.Exists)
    {
        return folder.GetFileSystemInfos().Length == 0;
    }

    throw new DirectoryNotFoundException();
}

Этот подход кажется нормальным. НО!! Это очень и очень плохо с точки зрения производительности. GetFileSystemInfos () - очень сложный метод. Фактически, он перечисляет все объекты файловой системы в папке, получает все их свойства, создает объекты, заполняет типизированный массив и т. Д. И все это просто для проверки длины. Это глупо, не правда ли?

Я только что профилировал такой код и определил, что ~ 250 вызовов такого метода выполняются за ~ 500 мс. Это очень медленно, и я считаю, что это можно сделать гораздо быстрее.

Есть предложения?

Ответы [ 18 ]

3 голосов
/ 16 апреля 2009

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

Directory.GetFiles(path);
&
Directory.GetDirectories(path);

должно повысить производительность, поскольку оба этих метода будут возвращать только массив строк с именами файлов / каталогов, а не целые объекты FileSystemInfo.

2 голосов
/ 21 марта 2013

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

public bool isDirectoryContainFiles(string path) {
    if (!Directory.Exists(path)) return false;
    return Directory.EnumerateFiles(path, "*", SearchOption.AllDirectories).Any();
}
2 голосов
/ 16 апреля 2009

Спасибо всем за ответы. Я пытался использовать Directory.GetFiles () и Directory.GetDirectories () методы. Хорошие новости! Производительность улучшилась в два раза! 229 звонков за 221мс. Но также я надеюсь, что можно избежать перечисления всех элементов в папке. Согласитесь, что все еще выполняется ненужная работа. Вам так не кажется?

После всех исследований я пришел к выводу, что под чистым .NET дальнейшая оптимизация невозможна. Я собираюсь поиграть с WinAPI FindFirstFile функцией. Надеюсь, это поможет.

1 голос
/ 15 октября 2018

На основании Брэд Паркс код:

    public static bool DirectoryIsEmpty(string path)
    {
        if (System.IO.Directory.GetFiles(path).Length > 0) return false;

        foreach (string dir in System.IO.Directory.GetDirectories(path))
            if (!DirectoryIsEmpty(dir)) return false;

        return true;
    }
0 голосов
/ 06 июня 2017

Вот кое-что, что может помочь вам сделать это. Мне удалось сделать это за две итерации.

 private static IEnumerable<string> GetAllNonEmptyDirectories(string path)
   {
     var directories =
        Directory.EnumerateDirectories(path, "*.*", SearchOption.AllDirectories)
        .ToList();

     var directoryList = 
     (from directory in directories
     let isEmpty = Directory.GetFiles(directory, "*.*", SearchOption.AllDirectories).Length == 0
     where !isEmpty select directory)
     .ToList();

     return directoryList.ToList();
   }
0 голосов
/ 06 сентября 2012

Используйте это. Это просто.

Public Function IsDirectoryEmpty(ByVal strDirectoryPath As String) As Boolean
        Dim s() As String = _
            Directory.GetFiles(strDirectoryPath)
        If s.Length = 0 Then
            Return True
        Else
            Return False
        End If
    End Function
0 голосов
/ 27 декабря 2009

Вам также следует заключить тест в блок try / catch, чтобы убедиться, что вы правильно обрабатываете исключение DirectoryNotFoundException. Это классическое условие гонки, если папка удаляется сразу после того, как вы проверили, существует ли она.

0 голосов
/ 16 апреля 2009

Мой код потрясающий, он просто занял 00: 00: 00.0007143 менее миллисекунды с 34 файлами в папке

   System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch();
    sw.Start();

     bool IsEmptyDirectory = (Directory.GetFiles("d:\\pdf").Length == 0);

     sw.Stop();
     Console.WriteLine(sw.Elapsed);
...