You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

VB.NET Dir方法迁移C#遇性能瓶颈,求Archive属性适配方案

VB.NET Dir方法结合Archive属性的C# .NET Core等效实现(高性能版)

一、Archive属性适配逻辑

VB.NET中用Dir方法结合FileAttribute.Archive筛选归档文件,在C#里可通过位运算判断文件属性:(文件属性 & FileAttributes.Archive) == FileAttributes.Archive,即可判定文件是否带有归档标记。

二、百万级文件场景性能优化要点

原生VB.NET的Dir方法基于Win32底层API实现,性能优异。如果你的C#代码用了Directory.GetFiles,会一次性将所有文件路径加载到内存,百万级目录下内存占用高、遍历速度慢。改用Directory.EnumerateFiles(延迟枚举,逐行返回结果)或直接调用Win32 API,能大幅降低内存开销、提升性能。

三、完整实现方案

方案1:基于.NET原生API的高性能实现

适合大多数场景,代码简洁且性能足够:

using System.IO;
using System.Linq;

// 判断目录下是否存在符合通配符的归档文件
public static bool ExistsMatchingArchiveFile(string directoryPath, string searchPattern)
{
    foreach (var filePath in Directory.EnumerateFiles(directoryPath, searchPattern, SearchOption.TopDirectoryOnly))
    {
        var attrs = File.GetAttributes(filePath);
        if ((attrs & FileAttributes.Archive) == FileAttributes.Archive)
        {
            return true;
        }
    }
    return false;
}

// 获取目录下所有符合通配符的归档文件
public static IEnumerable<string> GetAllArchiveFiles(string directoryPath, string searchPattern, SearchOption searchOption = SearchOption.TopDirectoryOnly)
{
    return Directory.EnumerateFiles(directoryPath, searchPattern, searchOption)
                    .Where(filePath => (File.GetAttributes(filePath) & FileAttributes.Archive) == FileAttributes.Archive);
}

方案2:Win32 API原生实现(与VB.NET Dir性能对齐)

如果对性能要求极高,直接调用Win32 API,和VB.NET Dir方法的底层逻辑完全一致:

using System;
using System.IO;
using System.Runtime.InteropServices;

public static class ArchiveFileSearcher
{
    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
    private struct WIN32_FIND_DATA
    {
        public FileAttributes 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, SetLastError = true)]
    private static extern IntPtr FindFirstFile(string lpFileName, out WIN32_FIND_DATA lpFindFileData);

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

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

    // 判断是否存在符合条件的归档文件
    public static bool ExistsArchiveFile(string directoryPath, string searchPattern)
    {
        var searchPath = Path.Combine(directoryPath, searchPattern);
        IntPtr findHandle = IntPtr.Zero;
        try
        {
            WIN32_FIND_DATA findData;
            findHandle = FindFirstFile(searchPath, out findData);
            if (findHandle == new IntPtr(-1))
                return false;

            do
            {
                // 跳过目录,只处理文件
                if ((findData.dwFileAttributes & FileAttributes.Directory) != FileAttributes.Directory)
                {
                    if ((findData.dwFileAttributes & FileAttributes.Archive) == FileAttributes.Archive)
                        return true;
                }
            } while (FindNextFile(findHandle, out findData));
            return false;
        }
        finally
        {
            if (findHandle != IntPtr.Zero && findHandle != new IntPtr(-1))
                FindClose(findHandle);
        }
    }

    // 获取所有符合条件的归档文件
    public static IEnumerable<string> GetArchiveFiles(string directoryPath, string searchPattern)
    {
        var searchPath = Path.Combine(directoryPath, searchPattern);
        IntPtr findHandle = IntPtr.Zero;
        try
        {
            WIN32_FIND_DATA findData;
            findHandle = FindFirstFile(searchPath, out findData);
            if (findHandle == new IntPtr(-1))
                yield break;

            do
            {
                if ((findData.dwFileAttributes & FileAttributes.Directory) != FileAttributes.Directory)
                {
                    if ((findData.dwFileAttributes & FileAttributes.Archive) == FileAttributes.Archive)
                    {
                        yield return Path.Combine(directoryPath, findData.cFileName);
                    }
                }
            } while (FindNextFile(findHandle, out findData));
        }
        finally
        {
            if (findHandle != IntPtr.Zero && findHandle != new IntPtr(-1))
                FindClose(findHandle);
        }
    }
}

四、使用提示

  • 若只需判断文件是否存在,优先用ExistsMatchingArchiveFile或ExistsArchiveFile,找到匹配项后立即返回,无需遍历所有文件。
  • 批量获取文件时,EnumerateFiles返回的是延迟序列,可配合foreach逐行处理,避免一次性加载所有数据到内存。
  • Win32 API实现需注意平台兼容性(仅支持Windows),若你的API需要跨平台,优先选择方案1。

内容的提问来源于stack exchange,提问作者Neeraj Kumar Gupta

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.21 23:27:05