Checking for files in a folder

I have a program that writes to the database which folders are full or empty. Now i use

bool hasFiles=false;
(Directory.GetFiles(path).Length >0) ? hasFiles=true: hasFiles=false;

but it takes almost one hour, and I can’t do anything at this time.

Is there a quickest way to check if there is any file in a folder?

+5
source share
6 answers

The key to speeding up this cross-network search is to reduce the number of queries over the network. Instead of getting all the directories and then checking each file, try and get everything from a single call.

.NET 3.5 , (. ). .NET 4 .

DirectoryInfo, , , .

, :

struct AllDirectories {
  public List<string> DirectoriesWithoutFiles { get; set; }
  public List<string> DirectoriesWithFiles { get; set; }
}

static class FileSystemScanner {
  public AllDirectories DivideDirectories(string startingPath) {
    var startingDir = new DirectoryInfo(startingPath);

    // allContent IList<FileSystemInfo>
    var allContent = GetAllFileSystemObjects(startingDir);
    var allFiles = allContent.Where(f => !(f.Attributes & FileAttributes.Directory))
                             .Cast<FileInfo>();
    var dirs = allContent.Where(f => (f.Attributes & FileAttributes.Directory))
                         .Cast<DirectoryInfo>();
    var allDirs = new SortedList<DirectoryInfo>(dirs, new FileSystemInfoComparer());

    var res = new AllDirectories {
      DirectoriesWithFiles = new List<string>()
    };
    foreach (var file in allFiles) {
      var dirName = Path.GetDirectoryName(file.Name);
      if (allDirs.Remove(dirName)) {
        // Was removed, so first time this dir name seen.
        res.DirectoriesWithFiles.Add(dirName);
      }
    }
    // allDirs now just contains directories without files
    res.DirectoriesWithoutFiles = new List<String>(addDirs.Select(d => d.Name));
  }

  class FileSystemInfoComparer : IComparer<FileSystemInfo> {
    public int Compare(FileSystemInfo l, FileSystemInfo r) {
      return String.Compare(l.Name, r.Name, StringComparison.OrdinalIgnoreCase);
    }
  }
}

GetAllFileSystemObjects .NET. .NET 4 :

ILIst<FileSystemInfo> GetAllFileSystemObjects(DirectoryInfo root) {
  return root.GetFileSystemInfos("*.*", SearchOptions.AllDirectories);
}

:

ILIst<FileSystemInfo> GetAllFileSystemObjects(DirectoryInfo root) {
  var res = new List<FileSystemInfo>();
  var pending = new Queue<DirectoryInfo>(new [] { root });

  while (pending.Count > 0) {
    var dir = pending.Dequeue();
    var content = dir.GetFileSystemInfos();
    res.AddRange(content);
    foreach (var dir in content.Where(f => (f.Attributes & FileAttributes.Directory))
                               .Cast<DirectoryInfo>()) {
      pending.Enqueue(dir);
    }
  }

  return res;
}

, .NET 4 , .

FileSystemInfo ( , ), , , ( P/Invoke FindFileFirst/FindNextFile/FindClose).


, :

Tuple<IEnumerable<T>,IEnumerable<T>> Extensions.Partition<T>(
                                                 this IEnumerable<T> input,
                                                 Func<T,bool> parition);

( , - , ).

+5

, - , .net 4, :

public bool isDirectoryContainFiles(string path) {
    if (!Directory.Exists(path)) return false;
    return Directory.EnumerateFiles(path, "*", SearchOption.AllDirectories).Any();
}
+9

.Net 4.0, EnumerateFiles. http://msdn.microsoft.com/en-us/library/dd413232(v=VS.100).aspx

GetFiles : EnumerateFiles, FileInfo ; GetFiles, FileInfo . , , EnumerateFiles .

, , 1 , .

+4

( ), , GetFiles() , 30k- .

CodeProject, .

... WebService , .

. , . , , . * 30k . , FindFirstFile , 0 1.

+3

, :

, . ( )

Are you doing this from a GUI application, in the main thread? If so, separate this process using BackgroundWorker. At least the application will still respond. You can also add checks for CancellationPendingin the method and cancel it if it takes too long.

Kind of tangential to your question - I just noticed and thought that I would comment.

+2
source

It is best to use the FindFirstFile API function. It does not take almost the same time.

0
source

All Articles