2

I'm writing a C# application with .NET 4 to read and process data files (*.dat) from a list of directories.

Currently, I'm checking if a directory contains files using the following function:

    private bool FilesPresent()
    {
        string[] DIRS = Directory.GetDirectories(dataFileDirectoryPath, "*.*", SearchOption.TopDirectoryOnly);
        foreach (string d in DIRS)
        {
            string[] FILES = Directory.GetFiles(d, "*.*", SearchOption.AllDirectories);
            if (FILES.Length > 0) { return true; }
        }
        return false;                
    }

I've also tried some alternative solutions from the following post: How to quickly check if folder is empty (.NET)?

It's important to note that some of the directories have in excess of 1,000,000 files. Even reading the million+ file names into a string[] is taking a long time.

How can I implement this differently so that it runs faster?

Putting it simply; I'd just like to know the fastest way of checking if the directory is not empty. I'm not concerned with retrieving the filenames at this time.

Community
  • 1
  • 1
Alfie J. Palmer
  • 827
  • 2
  • 15
  • 30
  • possible duplicate of [How to quickly check if folder is empty (.NET)?](http://stackoverflow.com/questions/755574/how-to-quickly-check-if-folder-is-empty-net) – Harry Jul 24 '15 at 08:04
  • I don't think you'll get any faster than the top answer in that duplicate. Why isn't that suitable? – Sayse Jul 24 '15 at 08:04
  • `Directory.EnumerateDirectories(dataFileDirectoryPath, "*.*", SearchOption.TopDirectoryOnly).Any(d => Directory.EnumerateFiles(d, "*.*", SearchOption.AllDirectories).Any())` – Tim Schmelter Jul 24 '15 at 08:06
  • Directory.EnumerateDirectories(folderPath,SearchOption.TopDirectoryOnly).SelectMany(x => x.EnumerateFiles()).Any(); – uk2k05 Jul 24 '15 at 08:10

2 Answers2

6

Starting from .NET 4.0 there are two methods, EnumerateDirectories/EnumerateFiles that lazily enumerate directories/files.

private static bool FilesPresent()
{
    IEnumerable<string> dirs = Directory.EnumerateDirectories(dataFileDirectoryPath, "*.*", SearchOption.TopDirectoryOnly);
    foreach (string d in dirs)
    {
        IEnumerable<string> files = Directory.EnumerateFiles(d, "*.*", SearchOption.AllDirectories);
        if (files.Any()) { return true; }
    }
    return false;
}

Technically you could rewrite it as:

private static bool FilesPresent()
{
    IEnumerable<string> dirs = Directory.EnumerateDirectories(dataFileDirectoryPath, "*.*", SearchOption.TopDirectoryOnly);
    return dirs.Any(d => Directory.EnumerateFiles(d, "*.*", SearchOption.AllDirectories).Any());
}

But I do feel it would make it more unreadable.

xanatos
  • 109,618
  • 12
  • 197
  • 280
3

Here's another approach using LINQ and EnumerateFileSystemEntries+AllDirectories:

bool noFiles = !Directory.EnumerateFileSystemEntries(dataFileDirectoryPath, "*.*", SearchOption.AllDirectories)
    .Any(entry => !File.GetAttributes(entry).HasFlag(FileAttributes.Directory));

If FileAttribute.HasFlag(FileAttributes.Directory) returns false it is a file.

Tim Schmelter
  • 450,073
  • 74
  • 686
  • 939