如何快速检查文件夹是否为空(.NET)?
我必须检查磁盘上的目录是否为空。 这意味着它不包含任何文件夹/文件。 我知道,有一个简单的方法。 我们获取 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 毫秒内执行。 这是非常慢的,我相信,可以做得更快。
有什么建议么?
I have to check, if directory on disk is empty. It means, that it does not contain any folders/files. I know, that there is a simple method. We get array of FileSystemInfo's and check if count of elements equals to zero. Something like that:
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();
}
This approach seems OK. BUT!! It is very, very bad from a perspective of performance. GetFileSystemInfos() is a very hard method. Actually, it enumerates all filesystem objects of folder, gets all their properties, creates objects, fills typed array etc. And all this just to simply check Length. That's stupid, isn't it?
I just profiled such code and determined, that ~250 calls of such method are executed in ~500ms. This is very slow and I believe, that it is possible to do it much quicker.
Any suggestions?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(18)
.NET 4 中的
Directory
和DirectoryInfo
中有一个新功能,允许它们返回IEnumerable
而不是数组,并开始返回结果在阅读所有目录内容之前。Directory.EnumerateFileSystemEntries
方法重载编辑:再次看到该答案,我意识到这段代码可以变得更简单......
There is a new feature in
Directory
andDirectoryInfo
in .NET 4 that allows them to return anIEnumerable
instead of an array, and start returning results before reading all the directory contents.Directory.EnumerateFileSystemEntries
method overloadsEDIT: seeing that answer again, I realize this code can be made much simpler...
这是我最终实现的超快速解决方案。 在这里,我使用 WinAPI 和函数 FindFirstFile、FindNextFile。 它可以避免枚举文件夹中的所有项目,并且在检测到文件夹中的第一个对象后立即停止。 这种方法比上面描述的要快 6(!!) 倍。 36 毫秒内 250 个调用!
我希望它对将来的某人有用。
Here is the extra fast solution, that I finally implemented. Here I am using WinAPI and functions FindFirstFile, FindNextFile. It allows to avoid enumeration of all items in Folder and stops right after detecting the first object in the Folder. This approach is ~6(!!) times faster, than described above. 250 calls in 36ms!
I hope it will be useful for somebody in the future.
您可以尝试
Directory.Exists(path)
和Directory.GetFiles(path)
- 可能会减少开销(没有对象 - 只是字符串等)。You could try
Directory.Exists(path)
andDirectory.GetFiles(path)
- probably less overhead (no objects - just strings etc).当文件夹为空以及包含子文件夹和文件夹时,此快速测试会在 2 毫秒内返回结果。 文件(5 个文件夹,每个文件夹 5 个文件)
This quick test came back in 2 milliseconds for the folder when empty and when containing subfolders & files (5 folders with 5 files in each)
我将其用于文件夹和文件(不知道这是否是最佳的)
I use this for folders and files (don't know if it's optimal)
如果您不介意离开纯 C# 并进行 WinApi 调用,那么您可能需要考虑 PathIsDirectoryEmpty() 函数。 根据MSDN,该函数:
这似乎是一个完全符合您想要的功能的函数,因此它可能针对该任务进行了很好的优化(尽管我还没有测试过)。
要从 C# 调用它,pinvoke.net 网站应该可以帮助您。 (不幸的是,它还没有描述这个特定的函数,但是你应该能够在那里找到一些具有相似参数和返回类型的函数,并将它们用作你的调用的基础。如果你再次查看 MSDN,它说:要导入的 DLL 是
shlwapi.dll
)If you don't mind leaving pure C# and going for WinApi calls, then you might want to consider the PathIsDirectoryEmpty() function. According to the MSDN, the function:
That seems to be a function which does exactly what you want, so it is probably well optimised for that task (although I haven't tested that).
To call it from C#, the pinvoke.net site should help you. (Unfortunately, it doesn't describe this certain function yet, but you should be able to find some functions with similar arguments and return type there and use them as the basis for your call. If you look again into the MSDN, it says that the DLL to import from is
shlwapi.dll
)我不知道这方面的性能统计数据,但是您是否尝试过使用
Directory.GetFiles()
静态方法?它返回一个包含文件名(不是 FileInfos)的字符串数组,您可以按照与上面相同的方式检查数组的长度。
I don't know about the performance statistics on this one, but have you tried using the
Directory.GetFiles()
static method ?It returns a string array containing filenames (not FileInfos) and you can check the length of the array in the same way as above.
我确信其他答案更快,并且您的问题询问文件夹是否包含文件或文件夹...但我认为大多数时候人们会认为目录是空的,如果它不包含文件。 即如果它包含空子目录,它对我来说仍然是“空”...这可能不适合您的使用,但可能适合其他人!
I'm sure the other answers are faster, and your question asked for whether or not a folder contained files or folders... but I'd think most of the time people would consider a directory empty if it contains no files. ie It's still "empty" to me if it contains empty subdirectories... this may not fit for your usage, but may for others!
简单又简单:
Easy and simple:
无论如何,您都必须从硬盘驱动器中获取此信息,仅此一项就胜过任何对象创建和数组填充。
You will have to go the hard drive for this information in any case, and this alone will trump any object creation and array filling.
我不知道有一种方法可以简洁地告诉您给定文件夹是否包含任何其他文件夹或文件,但是,使用:
应该有助于提高性能,因为这两种方法只会返回带有文件名称的字符串数组/目录而不是整个 FileSystemInfo 对象。
I'm not aware of a method that will succinctly tell you if a given folder contains any other folders or files, however, using:
should help performance since both of these methods will only return an array of strings with the names of the files/directories rather than entire FileSystemInfo objects.
谢谢大家的回复。 我尝试使用 Directory.GetFiles() 和 Directory.GetDirectories() 方法。 好消息! 性能提高了~两倍! 221 毫秒内有 229 个调用。 但我也希望可以避免枚举文件夹中的所有项目。 同意,不必要的工作仍在执行。 你不这么认为吗?
经过所有调查,我得出的结论是,在纯.NET下进一步优化是不可能的。 我将使用 WinAPI 的 FindFirstFile 函数。 希望它会有所帮助。
Thanks, everybody, for replies. I tried to use Directory.GetFiles() and Directory.GetDirectories() methods. Good news! The performance improved ~twice! 229 calls in 221ms. But also I hope, that it is possible to avoid enumeration of all items in the folder. Agree, that still the unnecessary job is executing. Don't you think so?
After all investigations, I reached a conclusion, that under pure .NET further optimiation is impossible. I am going to play with WinAPI's FindFirstFile function. Hope it will help.
有时您可能想验证子目录中是否存在任何文件并忽略那些空的子目录; 在这种情况下,您可以使用以下方法:
Some time you might want to verify whether any files exist inside sub directories and ignore those empty sub directories; in this case you can used method below:
基于 Brad Parks 代码:
Based in Brad Parks code:
我的代码太棒了,它只需要 00:00:00.0007143
文件夹中有 34 个文件,不到毫秒
My code is amazing it just took 00:00:00.0007143
less than milisecond with 34 file in folder
这里有一些东西可能会帮助你做到这一点。 我成功地通过两次迭代完成了它。
Here is something that might help you doing it. I managed to do it in two iterations.
由于无论如何您都将使用 DirectoryInfo 对象,所以我会使用扩展
Since you are going to work with a DirectoryInfo object anyway, I'd go with an extension
用这个。 这很简单。
Use this. It's simple.