不使用System.IO.FileInfo获取文件大小?

是否可以在不使用System.IO.FileInfo情况下在C#中获取文件的大小

我知道你可以分别使用Path.GetFileName(yourFilePath)Path.GetExtension(yourFilePath)来获取Name和Extension等其他内容,但显然不是文件大小? 有没有其他方法可以在不使用System.IO.FileInfo情况下获取文件大小

唯一的原因是,如果我是正确的,FileInfo会抓取比我真正需要的更多的信息,因此如果我需要的唯一东西是文件的大小,那么收集所有这些FileInfo需要更长的时间。 有更快的方法吗?

我使用这两种方法执行了基准测试:

  public static uint GetFileSizeA(string filename) { WIN32_FIND_DATA findData; FindFirstFile(filename, out findData); return findData.nFileSizeLow; } public static uint GetFileSizeB(string filename) { IntPtr handle = CreateFile( filename, FileAccess.Read, FileShare.Read, IntPtr.Zero, FileMode.Open, FileAttributes.ReadOnly, IntPtr.Zero); long fileSize; GetFileSizeEx(handle, out fileSize); CloseHandle(handle); return (uint) fileSize; } 

针对2300多个文件运行,GetFileSizeA需要62-63ms才能运行。 GetFileSizeB花了18秒。

除非有人看到我做错的事情,否则我认为答案很清楚哪种方法更快。

有没有办法可以避免实际打开文件?

更新

将FileAttributes.ReadOnly更改为FileAttributes.Normal减少了时间,以便两种方法的性能相同。

此外,如果你跳过CloseHandle()调用,GetFileSizeEx方法会快20到30%,但我不知道我会推荐它。

从我做过的一个简短的测试中,我发现使用FileStream平均比使用Pete的GetFileSizeB慢1毫秒(在网络共享上花了我大约21毫秒……)。 就我个人而言,我个人更喜欢保持在BCL限制范围内。

代码很简单:

 using (var file = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) { return file.Length; } 

根据这个评论 :

我有一个小应用程序收集大小信息并将其保存到一个数组…但我经常有五十万个文件,给予或采取,需要一段时间来通过所有这些文件(我正在使用FileInfo) 。 我只是想知道是否有更快的方式……

由于您找到了这么多文件的长度,因此您更有可能从并行化中受益,而不是尝试通过其他方法获取文件大小。 FileInfo类应该足够好 ,任何改进都可能很小。

另一方面,并​​行化文件大小请求有可能显着提高速度。 (请注意,改进程度将主要取决于您的磁盘驱动器,而不是您的处理器,因此结果可能会有很大差异。)

不是直接答案…因为我不确定使用.NET框架有更快的方法。

这是我正在使用的代码:

  List list = new List(); DirectoryInfo di = new DirectoryInfo("C:\\Program Files"); FileInfo[] fiArray = di.GetFiles("*", SearchOption.AllDirectories); foreach (FileInfo f in fiArray) list.Add(f.Length); 

运行它,我的“Program Files”目录运行了2709ms,大约是22720个文件。 无论如何,这都不是什么懈怠。 此外,当我将*.txt作为GetFiles方法的第一个参数的filter时,它将时间大幅减少到461ms。

很多这将取决于您的硬盘驱动器的速度,但我真的不认为FileInfo会破坏性能。

注意:我认为这仅对.NET 4+有效

你可以试试这个:

 [DllImport("kernel32.dll")] static extern bool GetFileSizeEx(IntPtr hFile, out long lpFileSize); 

但这并没有太大改善……

以下是从pinvoke.net获取的示例代码:

 IntPtr handle = CreateFile( PathString, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, FILE_ATTRIBUTE_READONLY, 0); //PInvoked too if (handle.ToInt32() == -1) { return; } long fileSize; bool result = GetFileSizeEx(handle, out fileSize); if (!result) { return; }