2010-12-04 61 views
12

这是一个很长的距离,但有没有更快的方式来获取大小,lastaccessedtime,最后创建时间等多个文件?获得多个FileInfo的更快方法?

我有一个很长的文件路径列表(所以我不需要枚举),并且需要尽快查找这些信息。并行创建FileInfo可能无济于事,因为瓶颈应该是磁盘。

NTFS日志只保留不幸的文件名,否则'很棒,我猜操作系统不会在某处存储元信息?

可能做,如果有一个静态或Win32调用(文件方法只允许我在同一时间得到一条信息虽然)方法获取的信息,而这产生了一堆的FileInfo的对象

另外一个优化

不管怎么说,很高兴,如果有人知道的东西,可能会帮助,不幸的是我必须要在这里做微优化,没有“使用数据库”是不是一个可行的答案;)

+0

看看通过NuGet的FluentPath。 http://weblogs.asp.net/bleroy/archive/2010/11/19/fluentpath-1-0.aspx – jvanrhyn 2010-12-04 09:16:43

+0

据我所知,这是一个更好的库处理文件路径和linq风格的操作,并没有与引擎盖下的文件元数据有很大关系 – Homde 2010-12-04 09:19:09

+0

如果没有,您是否可以缓存应用程序生命周期开始时的信息?这将在RAM中为您提供信息,但如果您有长时间运行的应用程序将不会更新。 – Patrick 2010-12-04 09:23:49

回答

8

System.IO.File有静态方法来得到你想要的。这是一个微型优化,但它可能是你需要的:GetLastAccessTimeGetCreationTime

编辑

我会留下上面的文字,因为您特别要求使用静态方法。不过,我认为你最好使用FileInfo(你应该确定)。 File和FileInfo都使用内部方法File,名为FillAttributeInfo来获取您之后的数据。对于您需要的属性,FileInfo需要调用此方法一次。 File将不得不在每次调用时调用它,因为方法结束时属性信息对象被抛弃(因为它是静态的)。

所以我的直觉是,当你需要多个属性时,每个文件的FileInfo会更快。但在表现情况下,您应该始终衡量!面对这个问题,我会尝试如上所述的两个托管选项,并在串行和并行运行时都做出基准测试。然后决定它是否足够快。

如果速度不够快,则需要直接调用Win32 API。在参考资源中查看File.FileAttributeInfo并且提出类似的内容并不难。

第二编辑

事实上,如果你真的需要它,这是调用Win32 API直接使用相同的方法,内部代号为File没有所需的代码,但使用一个操作系统调用来获取所有属性。我认为你应该只使用它,如果它真的需要。你必须从FILETIME解析到一个可用的日期时间,等等,所以你需要做更多的工作来手动完成。

static class FastFile 
{ 
    private const int MAX_PATH = 260; 
    private const int MAX_ALTERNATE = 14; 

    public static WIN32_FIND_DATA GetFileData(string fileName) 
    { 
     WIN32_FIND_DATA data; 
     IntPtr handle = FindFirstFile(fileName, out data); 
     if (handle == IntPtr.Zero) 
      throw new IOException("FindFirstFile failed"); 
     FindClose(handle); 
     return data; 
    } 

    [DllImport("kernel32")] 
    private static extern IntPtr FindFirstFile(string fileName, out WIN32_FIND_DATA data); 

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


    [StructLayout(LayoutKind.Sequential)] 
    public struct FILETIME 
    { 
     public uint dwLowDateTime; 
     public uint dwHighDateTime; 
    } 
    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] 
    public struct WIN32_FIND_DATA 
    { 
     public FileAttributes dwFileAttributes; 
     public FILETIME ftCreationTime; 
     public FILETIME ftLastAccessTime; 
     public FILETIME ftLastWriteTime; 
     public int nFileSizeHigh; 
     public int nFileSizeLow; 
     public int dwReserved0; 
     public int dwReserved1; 
     [MarshalAs(UnmanagedType.ByValTStr, SizeConst = MAX_PATH)] 
     public string cFileName; 
     [MarshalAs(UnmanagedType.ByValTStr, SizeConst = MAX_ALTERNATE)] 
     public string cAlternate; 
    } 
} 
2

是否有可能使用DirectoryInfo类?

DirectoryInfo d = new DirectoryInfo(@"c:\\Temp"); 
FileInfo[] f= d.GetFiles() 
4

.NET的DirectoryInfo中和的FileInfo类是慢得令人难以置信在这个问题上,与网络共享使用时尤其如此。

如果许多要“扫描”的文件位于同一个目录中,则通过使用Win32 API的FindFirstFile,FindNextFile和FindClose函数可以获得更快的结果(取决于具体情况:按维度更快)。如果您需要获取更多实际需要的信息(例如,如果您要求目录中的所有“.log”文件,其中只需要其中的75%),则情况更是如此。其实,.NET的info类也在内部使用这些Win32 API函数。但他们只是“删除”文件名。当要求获取更多关于一堆文件的信息(例如LastModified)时,每个文件都会有一个单独的(网络)请求,这会占用时间。

0

我认为你正在寻找GetFileAttributesEx函数(​​)。然而,FileInfo类(或者说,它的基类)在内部使用这个,所以我怀疑你会看到任何性能改进。