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);
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)) {
res.DirectoriesWithFiles.Add(dirName);
}
}
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);
( , - , ).