我有程序写入数据库文件夹已满或空.现在我正在使用
bool hasFiles=false;
(Directory.GetFiles(path).Length >0) ? hasFiles=true: hasFiles=false;
Run Code Online (Sandbox Code Playgroud)
但这需要将近一个小时,而我现在无能为力.
有没有最快的方法来检查文件夹是否有任何文件?
Len*_*eng 10
要检查目录或子目录中是否存在任何文件,请在.net 4中使用以下方法:
public bool isDirectoryContainFiles(string path) {
if (!Directory.Exists(path)) return false;
return Directory.EnumerateFiles(path, "*", SearchOption.AllDirectories).Any();
}
Run Code Online (Sandbox Code Playgroud)
加速这种跨网络搜索的关键是减少网络上的请求数量.而不是获取所有目录,然后检查每个目录,尝试通过一次调用获取所有内容.
在.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);
}
}
}
Run Code Online (Sandbox Code Playgroud)
实现GetAllFileSystemObjects
取决于.NET版本.在.NET 4上,它非常简单:
ILIst<FileSystemInfo> GetAllFileSystemObjects(DirectoryInfo root) {
return root.GetFileSystemInfos("*.*", SearchOptions.AllDirectories);
}
Run Code Online (Sandbox Code Playgroud)
在早期版本中,还需要做一些工作:
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;
}
Run Code Online (Sandbox Code Playgroud)
这种方法尽可能少地调用文件系统,在.NET 4上只调用一次,在早期版本的每个目录调用一次,允许网络客户端和服务器最小化底层文件系统调用和网络往返次数.
获取FileSystemInfo
实例的缺点是需要多个文件系统操作(我相信这在某种程度上取决于操作系统),但是对于每个名称,任何解决方案都需要知道它是文件还是目录,因此在某种程度上这是不可避免的(不需要求助于P) /调用FindFileFirst
/ FindNextFile
/ FindClose
).
除此之外,使用分区扩展方法会更容易:
Tuple<IEnumerable<T>,IEnumerable<T>> Extensions.Partition<T>(
this IEnumerable<T> input,
Func<T,bool> parition);
Run Code Online (Sandbox Code Playgroud)
把它写成懒惰将是一个有趣的练习(只有当某些东西在其中一个输出上迭代时才会消耗输入,同时缓冲另一个输出).