我必须判断磁盘上的目录是否为空.这意味着它不包含任何文件夹/文件.我知道,有一个简单的方法.我们获取文件系统信息数组,并判断元素数是否等于零.诸如此类:

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();
}

这种方法似乎还可以.但是从表现的Angular 来看,这是非常非常糟糕的.GetFileSystemInfos()是一个非常困难的方法.实际上,它枚举文件夹的所有文件系统对象,获取它们的所有属性,创建对象,填充类型化数组等等,所有这些只是为了简单地判断长度.这很愚蠢,不是吗?

我刚才分析了这样的代码,确定这样的方法的~250次调用是在~500ms内执行的.这是非常慢的,我相信有可能做得更快.

有什么建议吗?

推荐答案

以下是我最终实现的超快解决方案.这里我使用的是WinAPI和函数FindFirstFileFindNextFile.它允许避免枚举文件夹和stops right after detecting the first object in the Folder中的所有项目.此方法为~6(!!)比上面描述的要快几倍.在36毫秒内打250个电话!

private static readonly IntPtr INVALID_HANDLE_VALUE = new IntPtr(-1);

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
private struct WIN32_FIND_DATA
{
    public uint dwFileAttributes;
    public System.Runtime.InteropServices.ComTypes.FILETIME ftCreationTime;
    public System.Runtime.InteropServices.ComTypes.FILETIME ftLastAccessTime;
    public System.Runtime.InteropServices.ComTypes.FILETIME ftLastWriteTime;
    public uint nFileSizeHigh;
    public uint nFileSizeLow;
    public uint dwReserved0;
    public uint dwReserved1;
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)]
    public string cFileName;
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 14)]
    public string cAlternateFileName;
}

[DllImport("kernel32.dll", CharSet=CharSet.Auto)]
private static extern IntPtr FindFirstFile(string lpFileName, out WIN32_FIND_DATA lpFindFileData);

[DllImport("kernel32.dll", CharSet=CharSet.Auto)]
private static extern bool FindNextFile(IntPtr hFindFile, out WIN32_FIND_DATA lpFindFileData);

[DllImport("kernel32.dll")]
private static extern bool FindClose(IntPtr hFindFile);

public static bool CheckDirectoryEmpty_Fast(string path)
{
    if (string.IsNullOrEmpty(path))
    {
        throw new ArgumentNullException(path);
    }

    if (Directory.Exists(path))
    {
        if (path.EndsWith(Path.DirectorySeparatorChar.ToString()))
            path += "*";
        else
            path += Path.DirectorySeparatorChar + "*";

        WIN32_FIND_DATA findData;
        var findHandle = FindFirstFile(path, out findData);

        if (findHandle != INVALID_HANDLE_VALUE)
        {
            try
            {
                bool empty = true;
                do
                {
                    if (findData.cFileName != "." && findData.cFileName != "..")
                        empty = false;
                } while (empty && FindNextFile(findHandle, out findData));

                return empty;
            }
            finally
            {
                FindClose(findHandle);
            }
        }

        throw new Exception("Failed to get directory first file",
            Marshal.GetExceptionForHR(Marshal.GetHRForLastWin32Error()));
    }
    throw new DirectoryNotFoundException();
}

我希望它能在将来对某些人有用.

.net相关问答推荐

带有ASP.NET核心的Angular 项目模板.API试验

在 Inno Setup 中判断给定服务的依赖服务

为什么解码后的字节数组与原始字节数组不同?

如何在 Raspberry Pi 上托管 WASM 文件?

是否存在指定的(子)索引分隔符?

使用 MassTransit、.NET Core 和 RabbitMQ 的设计挑战

线程安全性的单元测试?

为什么具有可为空值的 struct 的 HashSet 非常慢?

在一个 LINQ 查询中获取两列的总和

.Include() 与 .Load() 在 EntityFramework 中的性能

如何在任务栏顶部全屏显示 Windows 窗体?

为什么我得到 411 Length required 错误?

C# 时间跨度毫秒与 TotalMilliseconds

我应该默认推荐密封类吗?

注册 COM 互操作与使程序集 COM 可见

msbuild,定义条件编译符号

.net 自定义配置如何不区分大小写解析枚举 ConfigurationProperty

在 C# 中,为什么不能将 List 对象存储在 List 变量中

.NET 的 XPath 和 XSLT 2.0?

WPF中的依赖属性和附加属性有什么区别?